From 13d545c3fd6c9889109dc64b035040b9d4741ed3 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 13 Aug 2015 16:58:04 -1000 Subject: [PATCH] Added explicit Big/Little method suffix --- atdna/main.cpp | 221 ++++++++++++------- atdna/test.hpp | 11 +- include/Athena/IStreamReader.hpp | 364 +++++++++++++++++++++++++++++++ include/Athena/IStreamWriter.hpp | 298 +++++++++++++++++++++++++ 4 files changed, 802 insertions(+), 92 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index ad0c05f..849ffae 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -123,7 +123,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor std::string GetOpString(const clang::Type* theType, unsigned width, const std::string& fieldName, bool writerPass, - bool& isDNATypeOut) + const std::string& funcPrefix, bool& isDNATypeOut) { isDNATypeOut = false; if (writerPass) @@ -140,29 +140,29 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor if (width == 8) return ATHENA_DNA_WRITER ".writeUByte(" + fieldName + ");"; else if (width == 16) - return ATHENA_DNA_WRITER ".writeUint16(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeUint16" + funcPrefix + "(" + fieldName + ");"; else if (width == 32) - return ATHENA_DNA_WRITER ".writeUint32(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeUint32" + funcPrefix + "(" + fieldName + ");"; else if (width == 64) - return ATHENA_DNA_WRITER ".writeUint64(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeUint64" + funcPrefix + "(" + fieldName + ");"; } else if (bType->isSignedInteger()) { if (width == 8) return ATHENA_DNA_WRITER ".writeByte(" + fieldName + ");"; else if (width == 16) - return ATHENA_DNA_WRITER ".writeInt16(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeInt16" + funcPrefix + "(" + fieldName + ");"; else if (width == 32) - return ATHENA_DNA_WRITER ".writeInt32(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeInt32" + funcPrefix + "(" + fieldName + ");"; else if (width == 64) - return ATHENA_DNA_WRITER ".writeInt64(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeInt64" + funcPrefix + "(" + fieldName + ");"; } else if (bType->isFloatingPoint()) { if (width == 32) - return ATHENA_DNA_WRITER ".writeFloat(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeFloat" + funcPrefix + "(" + fieldName + ");"; else if (width == 64) - return ATHENA_DNA_WRITER ".writeDouble(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeDouble" + funcPrefix + "(" + fieldName + ");"; } } else if (theType->isRecordType()) @@ -180,11 +180,11 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor context.getTypeInfo(eType).Width != 32) continue; if (vType->getNumElements() == 2) - return ATHENA_DNA_WRITER ".writeVec2f(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeVec2f" + funcPrefix + "(" + fieldName + ");"; else if (vType->getNumElements() == 3) - return ATHENA_DNA_WRITER ".writeVec3f(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeVec3f" + funcPrefix + "(" + fieldName + ");"; else if (vType->getNumElements() == 4) - return ATHENA_DNA_WRITER ".writeVec4f(" + fieldName + ");"; + return ATHENA_DNA_WRITER ".writeVec4f" + funcPrefix + "(" + fieldName + ");"; } } } @@ -211,29 +211,29 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor if (width == 8) return ATHENA_DNA_READER ".readUByte()"; else if (width == 16) - return ATHENA_DNA_READER ".readUint16()"; + return ATHENA_DNA_READER ".readUint16" + funcPrefix + "()"; else if (width == 32) - return ATHENA_DNA_READER ".readUint32()"; + return ATHENA_DNA_READER ".readUint32" + funcPrefix + "()"; else if (width == 64) - return ATHENA_DNA_READER ".readUint64()"; + return ATHENA_DNA_READER ".readUint64" + funcPrefix + "()"; } else if (bType->isSignedInteger()) { if (width == 8) return ATHENA_DNA_READER ".readByte()"; else if (width == 16) - return ATHENA_DNA_READER ".readInt16()"; + return ATHENA_DNA_READER ".readInt16" + funcPrefix + "()"; else if (width == 32) - return ATHENA_DNA_READER ".readInt32()"; + return ATHENA_DNA_READER ".readInt32" + funcPrefix + "()"; else if (width == 64) - return ATHENA_DNA_READER ".readInt64()"; + return ATHENA_DNA_READER ".readInt64" + funcPrefix + "()"; } else if (bType->isFloatingPoint()) { if (width == 32) - return ATHENA_DNA_READER ".readFloat()"; + return ATHENA_DNA_READER ".readFloat" + funcPrefix + "()"; else if (width == 64) - return ATHENA_DNA_READER ".readDouble()"; + return ATHENA_DNA_READER ".readDouble" + funcPrefix + "()"; } } else if (theType->isRecordType()) @@ -251,11 +251,11 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor context.getTypeInfo(eType).Width != 32) continue; if (vType->getNumElements() == 2) - return ATHENA_DNA_READER ".readVec2f()"; + return ATHENA_DNA_READER ".readVec2f" + funcPrefix + "()"; else if (vType->getNumElements() == 3) - return ATHENA_DNA_READER ".readVec3f()"; + return ATHENA_DNA_READER ".readVec3f" + funcPrefix + "()"; else if (vType->getNumElements() == 4) - return ATHENA_DNA_READER ".readVec4f()"; + return ATHENA_DNA_READER ".readVec4f" + funcPrefix + "()"; } } } @@ -430,7 +430,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor fileOut << "void " << decl->getQualifiedNameAsString() << "::write(Athena::io::IStreamWriter& " ATHENA_DNA_WRITER ") const\n{\n"; else fileOut << "void " << decl->getQualifiedNameAsString() << "::read(Athena::io::IStreamReader& " ATHENA_DNA_READER ")\n{\n"; - int currentEndian = -1; if (baseDNA.size()) { @@ -445,7 +444,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor clang::QualType qualType = field->getType(); clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); const clang::Type* regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Elaborated) + while (regType->getTypeClass() == clang::Type::Elaborated || + regType->getTypeClass() == clang::Type::Typedef) regType = regType->getUnqualifiedDesugaredType(); /* Resolve constant array */ @@ -506,24 +506,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor } } - clang::QualType templateType; - std::string ioOp; - bool isDNAType = false; - const clang::TemplateArgument* typeArg = nullptr; for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Type) - { - typeArg = &arg; - templateType = arg.getAsType().getCanonicalType(); - const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); - ioOp = GetOpString(type, regTypeInfo.Width, fieldName, p, isDNAType); - } - else if (arg.getKind() == clang::TemplateArgument::Expression) + if (arg.getKind() == clang::TemplateArgument::Expression) { const clang::Expr* expr = arg.getAsExpr(); endianExpr = expr; - if (expr->isIntegerConstantExpr(endian, context)) + if (!expr->isIntegerConstantExpr(endian, context)) { if (!p) { @@ -557,6 +546,27 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor continue; } + std::string funcPrefix; + if (endianVal == 0) + funcPrefix = "Little"; + else if (endianVal == 1) + funcPrefix = "Big"; + + clang::QualType templateType; + std::string ioOp; + bool isDNAType = false; + const clang::TemplateArgument* typeArg = nullptr; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + templateType = arg.getAsType().getCanonicalType(); + const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); + ioOp = GetOpString(type, regTypeInfo.Width, fieldName, p, funcPrefix, isDNAType); + } + } + if (ioOp.empty()) { if (!p) @@ -568,15 +578,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor continue; } - if (currentEndian != endianVal) - { - if (endianVal == 0) - fileOut << (p ? " " ATHENA_DNA_WRITER ".setEndian(Athena::LittleEndian);\n" : " " ATHENA_DNA_READER ".setEndian(Athena::LittleEndian);\n"); - else if (endianVal == 1) - fileOut << (p ? " " ATHENA_DNA_WRITER ".setEndian(Athena::BigEndian);\n" : " " ATHENA_DNA_READER ".setEndian(Athena::BigEndian);\n"); - currentEndian = endianVal; - } - fileOut << " /* " << fieldName << " */\n"; if (!p) fileOut << " " << fieldName << " = " << ioOp << ";\n"; @@ -608,25 +609,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor } } - clang::QualType templateType; - std::string ioOp; - bool isDNAType = false; std::string sizeExpr; - const clang::TemplateArgument* typeArg = nullptr; const clang::TemplateArgument* sizeArg = nullptr; size_t idx = 0; bool bad = false; for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Type) - { - typeArg = &arg; - templateType = arg.getAsType().getCanonicalType(); - clang::TypeInfo typeInfo = context.getTypeInfo(templateType); - static const std::string elemStr = "elem"; - ioOp = GetOpString(templateType.getTypePtr(), typeInfo.Width, elemStr, p, isDNAType); - } - else if (arg.getKind() == clang::TemplateArgument::Expression) + if (arg.getKind() == clang::TemplateArgument::Expression) { const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); if (idx == 1) @@ -685,6 +674,28 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor continue; } + std::string funcPrefix; + if (endianVal == 0) + funcPrefix = "Little"; + else if (endianVal == 1) + funcPrefix = "Big"; + + clang::QualType templateType; + std::string ioOp; + bool isDNAType = false; + const clang::TemplateArgument* typeArg = nullptr; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + templateType = arg.getAsType().getCanonicalType(); + clang::TypeInfo typeInfo = context.getTypeInfo(templateType); + static const std::string elemStr = "elem"; + ioOp = GetOpString(templateType.getTypePtr(), typeInfo.Width, elemStr, p, funcPrefix, isDNAType); + } + } + if (ioOp.empty()) { if (!p) @@ -707,20 +718,14 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor continue; } - if (currentEndian != endianVal) - { - if (endianVal == 0) - fileOut << (p ? " " ATHENA_DNA_WRITER ".setEndian(Athena::LittleEndian);\n" : " " ATHENA_DNA_READER ".setEndian(Athena::LittleEndian);\n"); - else if (endianVal == 1) - fileOut << (p ? " " ATHENA_DNA_WRITER ".setEndian(Athena::BigEndian);\n" : " " ATHENA_DNA_READER ".setEndian(Athena::BigEndian);\n"); - currentEndian = endianVal; - } + if (isDNAType) + funcPrefix.clear(); fileOut << " /* " << fieldName << " */\n"; if (!p) - fileOut << " " ATHENA_DNA_READER ".enumerate(" << fieldName << ", " << sizeExpr << ");\n"; + fileOut << " " ATHENA_DNA_READER ".enumerate" << funcPrefix << "(" << fieldName << ", " << sizeExpr << ");\n"; else - fileOut << " " ATHENA_DNA_WRITER ".enumerate(" << fieldName << ");\n"; + fileOut << " " ATHENA_DNA_WRITER ".enumerate" << funcPrefix << "(" << fieldName << ");\n"; } else if (!tsDecl->getName().compare("Buffer")) @@ -909,21 +914,18 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor continue; } - if (currentEndian != endianVal) - { - if (endianVal == 0) - fileOut << (p ? " " ATHENA_DNA_WRITER ".setEndian(Athena::LittleEndian);\n" : " " ATHENA_DNA_READER ".setEndian(Athena::LittleEndian);\n"); - else if (endianVal == 1) - fileOut << (p ? " " ATHENA_DNA_WRITER ".setEndian(Athena::BigEndian);\n" : " " ATHENA_DNA_READER ".setEndian(Athena::BigEndian);\n"); - currentEndian = endianVal; - } + std::string funcPrefix; + if (endianVal == 0) + funcPrefix = "Little"; + else if (endianVal == 1) + funcPrefix = "Big"; fileOut << " /* " << fieldName << " */\n"; if (!p) - fileOut << " " << fieldName << " = " ATHENA_DNA_READER ".readWString(" << sizeExprStr << ");\n"; + fileOut << " " << fieldName << " = " ATHENA_DNA_READER ".readWString" << funcPrefix << "(" << sizeExprStr << ");\n"; else { - fileOut << " " ATHENA_DNA_WRITER ".writeWString(" << fieldName; + fileOut << " " ATHENA_DNA_WRITER ".writeWString" << funcPrefix << "(" << fieldName; if (sizeExprStr.size()) fileOut << ", " << sizeExprStr; fileOut << ");\n"; @@ -931,6 +933,29 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor } else if (!tsDecl->getName().compare("WStringAsString")) { + llvm::APSInt endian(64, -1); + const clang::Expr* endianExpr = nullptr; + if (classParms->size() >= 2) + { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) + { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + endianExpr = defArg; + if (!defArg->isIntegerConstantExpr(endian, context)) + { + if (!p) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true)); + } + continue; + } + } + } + const clang::Expr* sizeExpr = nullptr; std::string sizeExprStr; for (const clang::TemplateArgument& arg : *tsType) @@ -957,12 +982,40 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor } } + + int endianVal = endian.getSExtValue(); + if (endianVal != 0 && endianVal != 1) + { + if (!p) + { + if (endianExpr) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true)); + } + else + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + } + continue; + } + + std::string funcPrefix; + if (endianVal == 0) + funcPrefix = "Little"; + else if (endianVal == 1) + funcPrefix = "Big"; + fileOut << " /* " << fieldName << " */\n"; if (!p) - fileOut << " " << fieldName << " = " ATHENA_DNA_READER ".readWStringAsString(" << sizeExprStr << ");\n"; + fileOut << " " << fieldName << " = " ATHENA_DNA_READER ".readWStringAsString" << funcPrefix << "(" << sizeExprStr << ");\n"; else { - fileOut << " " ATHENA_DNA_WRITER ".writeStringAsWString(" << fieldName; + fileOut << " " ATHENA_DNA_WRITER ".writeStringAsWString" << funcPrefix << "(" << fieldName; if (sizeExprStr.size()) fileOut << ", " << sizeExprStr; fileOut << ");\n"; @@ -1131,7 +1184,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { fileOut << " /* " << fieldName << " */\n" " " << fieldName << (p ? ".write(" ATHENA_DNA_WRITER ");\n" : ".read(" ATHENA_DNA_READER ");\n"); - currentEndian = -1; break; } } @@ -1167,7 +1219,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor clang::QualType qualType = field->getType(); clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); const clang::Type* regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Elaborated) + while (regType->getTypeClass() == clang::Type::Elaborated || + regType->getTypeClass() == clang::Type::Typedef) regType = regType->getUnqualifiedDesugaredType(); /* Resolve constant array */ diff --git a/atdna/test.hpp b/atdna/test.hpp index beb202d..a0cf133 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -5,7 +5,6 @@ typedef io::DNAYaml BigDNA; struct TESTSubFile : public BigDNA { - DECL_DNA DECL_YAML Value sub1; Value sub2; @@ -13,7 +12,6 @@ struct TESTSubFile : public BigDNA struct TESTSubClassFile : public TESTSubFile { - DECL_DNA DECL_YAML Value sub3; Value sub4; @@ -21,7 +19,6 @@ struct TESTSubClassFile : public TESTSubFile struct TESTSubSubClassFile : public TESTSubClassFile { - DECL_DNA DECL_YAML Value sub5; Value sub6; @@ -29,7 +26,6 @@ struct TESTSubSubClassFile : public TESTSubClassFile struct TESTFile : public BigDNA { - DECL_DNA DECL_YAML Value varBool; Value var32; @@ -39,25 +35,24 @@ struct TESTFile : public BigDNA struct TESTNestedSubFile : public BigDNA { - DECL_DNA DECL_YAML Value nestSub1; Value nestSub2; } nestedSubFile; - TESTSubFile subFile; + using TESTSubFileUsing = TESTSubFile; + TESTSubFileUsing subFile; Align<4> align; struct TESTExplicitSubFile : public BigDNA { - DECL_EXPLICIT_DNA DECL_YAML Value explSub1; Value explSub2; } explSubFile; - Value arrCount[2]; + Value arrCount[2]; Vector array; Seek<21, Current> seek; diff --git a/include/Athena/IStreamReader.hpp b/include/Athena/IStreamReader.hpp index cecb41c..8203fad 100644 --- a/include/Athena/IStreamReader.hpp +++ b/include/Athena/IStreamReader.hpp @@ -135,6 +135,26 @@ public: inline atInt16 readVal(typename std::enable_if::value>::type* = 0) {return readInt16();} + inline atInt16 readInt16Little() + { + atInt16 val; + readUBytesToBuf(&val, 2); + return utility::LittleInt16(val); + } + template + inline atInt16 readValLittle(typename std::enable_if::value>::type* = 0) + {return readInt16Little();} + + inline atInt16 readInt16Big() + { + atInt16 val; + readUBytesToBuf(&val, 2); + return utility::BigInt16(val); + } + template + inline atInt16 readValBig(typename std::enable_if::value>::type* = 0) + {return readInt16Big();} + /*! \brief Reads a Uint16 and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -149,6 +169,26 @@ public: inline atUint16 readVal(typename std::enable_if::value>::type* = 0) {return readUint16();} + inline atUint16 readUint16Little() + { + atUint16 val; + readUBytesToBuf(&val, 2); + return utility::LittleUint16(val); + } + template + inline atUint16 readValLittle(typename std::enable_if::value>::type* = 0) + {return readUint16Little();} + + inline atUint16 readUint16Big() + { + atUint16 val; + readUBytesToBuf(&val, 2); + return utility::BigUint16(val); + } + template + inline atUint16 readValBig(typename std::enable_if::value>::type* = 0) + {return readUint16Big();} + /*! \brief Reads a Int32 and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -167,6 +207,26 @@ public: inline atInt32 readVal(typename std::enable_if::value>::type* = 0) {return readInt32();} + inline atInt32 readInt32Little() + { + atInt32 val; + readUBytesToBuf(&val, 4); + return utility::LittleInt32(val); + } + template + inline atInt32 readValLittle(typename std::enable_if::value>::type* = 0) + {return readInt32Little();} + + inline atInt32 readInt32Big() + { + atInt32 val; + readUBytesToBuf(&val, 4); + return utility::BigInt32(val); + } + template + inline atInt32 readValBig(typename std::enable_if::value>::type* = 0) + {return readInt32Big();} + /*! \brief Reads a Uint32 and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -181,6 +241,26 @@ public: inline atUint32 readVal(typename std::enable_if::value>::type* = 0) {return readUint32();} + inline atUint32 readUint32Little() + { + atUint32 val; + readUBytesToBuf(&val, 4); + return utility::LittleUint32(val); + } + template + inline atInt32 readValLittle(typename std::enable_if::value>::type* = 0) + {return readUint32Little();} + + inline atUint32 readUint32Big() + { + atUint32 val; + readUBytesToBuf(&val, 4); + return utility::BigUint32(val); + } + template + inline atUint32 readValBig(typename std::enable_if::value>::type* = 0) + {return readUint32Big();} + /*! \brief Reads a Int64 and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -199,6 +279,26 @@ public: inline atInt64 readVal(typename std::enable_if::value>::type* = 0) {return readInt64();} + inline atInt64 readInt64Little() + { + atInt64 val; + readUBytesToBuf(&val, 8); + return utility::LittleInt64(val); + } + template + inline atInt64 readValLittle(typename std::enable_if::value>::type* = 0) + {return readInt64Little();} + + inline atInt64 readInt64Big() + { + atInt64 val; + readUBytesToBuf(&val, 8); + return utility::BigInt64(val); + } + template + inline atInt64 readValBig(typename std::enable_if::value>::type* = 0) + {return readInt64Big();} + /*! \brief Reads a Uint64 and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -213,6 +313,26 @@ public: inline atUint64 readVal(typename std::enable_if::value>::type* = 0) {return readUint64();} + inline atUint64 readUint64Little() + { + atUint64 val; + readUBytesToBuf(&val, 8); + return utility::LittleUint64(val); + } + template + inline atUint64 readValLittle(typename std::enable_if::value>::type* = 0) + {return readUint64Little();} + + inline atUint64 readUint64Big() + { + atUint64 val; + readUBytesToBuf(&val, 8); + return utility::BigUint64(val); + } + template + inline atUint64 readValBig(typename std::enable_if::value>::type* = 0) + {return readUint64Big();} + /*! \brief Reads a float and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -231,6 +351,26 @@ public: inline float readVal(typename std::enable_if::value>::type* = 0) {return readFloat();} + inline float readFloatLittle() + { + float val; + readUBytesToBuf(&val, 4); + return utility::LittleFloat(val); + } + template + inline float readValLittle(typename std::enable_if::value>::type* = 0) + {return readFloatLittle();} + + inline float readFloatBig() + { + float val; + readUBytesToBuf(&val, 4); + return utility::BigFloat(val); + } + template + inline float readValBig(typename std::enable_if::value>::type* = 0) + {return readFloatBig();} + /*! \brief Reads a double and swaps to proper endianness depending on platform * and Stream settings, and advances the current position * @@ -249,6 +389,26 @@ public: inline double readVal(typename std::enable_if::value>::type* = 0) {return readDouble();} + inline double readDoubleLittle() + { + double val; + readUBytesToBuf(&val, 8); + return utility::LittleDouble(val); + } + template + inline double readValLittle(typename std::enable_if::value>::type* = 0) + {return readDoubleLittle();} + + inline double readDoubleBig() + { + double val; + readUBytesToBuf(&val, 8); + return utility::BigDouble(val); + } + template + inline double readValBig(typename std::enable_if::value>::type* = 0) + {return readDoubleBig();} + /*! \brief Reads a bool and advances the current position * * \return bool The value at the current address @@ -289,6 +449,30 @@ public: inline atVec2f readVal(typename std::enable_if::value>::type* = 0) {return readVec2f();} + inline atVec2f readVec2fLittle() + { + atVec2f val; + readUBytesToBuf(&val, 8); + utility::LittleFloat(val.vec[0]); + utility::LittleFloat(val.vec[1]); + return val; + } + template + inline atVec2f readValLittle(typename std::enable_if::value>::type* = 0) + {return readVec2fLittle();} + + inline atVec2f readVec2fBig() + { + atVec2f val; + readUBytesToBuf(&val, 8); + utility::BigFloat(val.vec[0]); + utility::BigFloat(val.vec[1]); + return val; + } + template + inline atVec2f readValBig(typename std::enable_if::value>::type* = 0) + {return readVec2fBig();} + /*! \brief Reads an atVec3f (12 bytes) and advances the current position * * \return atVec3f The value at the current address @@ -316,6 +500,32 @@ public: inline atVec3f readVal(typename std::enable_if::value>::type* = 0) {return readVec3f();} + inline atVec3f readVec3fLittle() + { + atVec3f val; + readUBytesToBuf(&val, 12); + utility::LittleFloat(val.vec[0]); + utility::LittleFloat(val.vec[1]); + utility::LittleFloat(val.vec[2]); + return val; + } + template + inline atVec3f readValLittle(typename std::enable_if::value>::type* = 0) + {return readVec3fLittle();} + + inline atVec3f readVec3fBig() + { + atVec3f val; + readUBytesToBuf(&val, 12); + utility::BigFloat(val.vec[0]); + utility::BigFloat(val.vec[1]); + utility::BigFloat(val.vec[2]); + return val; + } + template + inline atVec3f readValBig(typename std::enable_if::value>::type* = 0) + {return readVec3fBig();} + /*! \brief Reads an atVec4f (16 bytes) and advances the current position * * \return atVec4f The value at the current address @@ -345,6 +555,34 @@ public: inline atVec4f readVal(typename std::enable_if::value>::type* = 0) {return readVec4f();} + inline atVec4f readVec4fLittle() + { + atVec4f val; + readUBytesToBuf(&val, 16); + utility::LittleFloat(val.vec[0]); + utility::LittleFloat(val.vec[1]); + utility::LittleFloat(val.vec[2]); + utility::LittleFloat(val.vec[3]); + return val; + } + template + inline atVec4f readValLittle(typename std::enable_if::value>::type* = 0) + {return readVec4fLittle();} + + inline atVec4f readVec4fBig() + { + atVec4f val; + readUBytesToBuf(&val, 16); + utility::BigFloat(val.vec[0]); + utility::BigFloat(val.vec[1]); + utility::BigFloat(val.vec[2]); + utility::BigFloat(val.vec[3]); + return val; + } + template + inline atVec4f readValBig(typename std::enable_if::value>::type* = 0) + {return readVec4fBig();} + /*! \brief Reads a wide-char string, converts to UTF8 and advances the position in the file * * \param fixedLen If non-negative, this is a fixed-length string read @@ -376,6 +614,56 @@ public: return conv.to_bytes(tmp); } + inline std::string readWStringAsStringLittle(atInt32 fixedLen = -1) + { + std::wstring tmp; + atUint16 chr = readUint16Little(); + + atInt32 i; + for (i = 0 ;; ++i) + { + if (fixedLen >= 0 && i >= fixedLen - 1) + break; + + if (!chr) + break; + + tmp.push_back(chr); + chr = readUint16Little(); + } + + if (fixedLen >= 0 && i < fixedLen) + seek(fixedLen - i); + + std::wstring_convert> conv; + return conv.to_bytes(tmp); + } + + inline std::string readWStringAsStringBig(atInt32 fixedLen = -1) + { + std::wstring tmp; + atUint16 chr = readUint16Big(); + + atInt32 i; + for (i = 0 ;; ++i) + { + if (fixedLen >= 0 && i >= fixedLen - 1) + break; + + if (!chr) + break; + + tmp.push_back(chr); + chr = readUint16Big(); + } + + if (fixedLen >= 0 && i < fixedLen) + seek(fixedLen - i); + + std::wstring_convert> conv; + return conv.to_bytes(tmp); + } + /*! \brief Reads a string and advances the position in the file * * \param fixedLen If non-negative, this is a fixed-length string read @@ -438,6 +726,56 @@ public: inline std::wstring readVal(typename std::enable_if::value>::type* = 0) {return readWString();} + inline std::wstring readWStringLittle(atInt32 fixedLen = -1) + { + std::wstring ret; + atUint16 chr = readUint16Little(); + + atInt32 i; + for (i = 1 ; chr != 0 ; ++i) + { + ret += chr; + + if (fixedLen >= 0 && i >= fixedLen) + break; + + chr = readUint16Little(); + } + + if (fixedLen >= 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + inline std::wstring readValLittle(typename std::enable_if::value>::type* = 0) + {return readWStringLittle();} + + inline std::wstring readWStringBig(atInt32 fixedLen = -1) + { + std::wstring ret; + atUint16 chr = readUint16Big(); + + atInt32 i; + for (i = 1 ; chr != 0 ; ++i) + { + ret += chr; + + if (fixedLen >= 0 && i >= fixedLen) + break; + + chr = readUint16Big(); + } + + if (fixedLen >= 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + inline std::wstring readValBig(typename std::enable_if::value>::type* = 0) + {return readWStringBig();} + template void enumerate(std::vector& vector, size_t count, typename std::enable_if::value || @@ -451,6 +789,32 @@ public: vector.emplace_back(readVal()); } + template + void enumerateLittle(std::vector& vector, size_t count, + typename std::enable_if::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) + { + vector.clear(); + vector.reserve(count); + for (size_t i=0 ; i()); + } + + template + void enumerateBig(std::vector& vector, size_t count, + typename std::enable_if::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) + { + vector.clear(); + vector.reserve(count); + for (size_t i=0 ; i()); + } + template void enumerate(std::vector& vector, size_t count, typename std::enable_if::value && diff --git a/include/Athena/IStreamWriter.hpp b/include/Athena/IStreamWriter.hpp index 9ad09e3..bdda703 100644 --- a/include/Athena/IStreamWriter.hpp +++ b/include/Athena/IStreamWriter.hpp @@ -115,6 +115,20 @@ public: } inline void writeVal(atInt16 val) {return writeInt16(val);} + inline void writeInt16Little(atInt16 val) + { + utility::LittleInt16(val); + writeUBytes((atUint8*)&val, 2); + } + inline void writeValLittle(atInt16 val) {return writeInt16Little(val);} + + inline void writeInt16Big(atInt16 val) + { + utility::BigInt16(val); + writeUBytes((atUint8*)&val, 2); + } + inline void writeValBig(atInt16 val) {return writeInt16Big(val);} + /*! \brief Writes an Uint16 to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings * @@ -124,6 +138,12 @@ public: inline void writeUint16(atUint16 val) {writeInt16(val);} inline void writeVal(atUint16 val) {return writeUint16(val);} + inline void writeUint16Little(atUint16 val) {writeInt16Little(val);} + inline void writeValLittle(atUint16 val) {return writeUint16Little(val);} + + inline void writeUint16Big(atUint16 val) {writeInt16Big(val);} + inline void writeValBig(atUint16 val) {return writeUint16Big(val);} + /*! \brief Writes an Int32 to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -140,6 +160,20 @@ public: } inline void writeVal(atInt32 val) {return writeInt32(val);} + inline void writeInt32Little(atInt32 val) + { + utility::LittleInt32(val); + writeUBytes((atUint8*)&val, 4); + } + inline void writeValLittle(atInt32 val) {return writeInt32Little(val);} + + inline void writeInt32Big(atInt32 val) + { + utility::BigInt32(val); + writeUBytes((atUint8*)&val, 4); + } + inline void writeValBig(atInt32 val) {return writeInt32Big(val);} + /*! \brief Writes an Uint32 to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -149,6 +183,12 @@ public: inline void writeUint32(atUint32 val) {writeInt32(val);} inline void writeVal(atUint32 val) {return writeUint32(val);} + inline void writeUint32Little(atUint32 val) {writeInt32Little(val);} + inline void writeValLittle(atUint32 val) {return writeUint32Little(val);} + + inline void writeUint32Big(atUint32 val) {writeInt32Big(val);} + inline void writeValBig(atUint32 val) {return writeUint32Big(val);} + /*! \brief Writes an Int64 to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -165,6 +205,20 @@ public: } inline void writeVal(atInt64 val) {return writeInt64(val);} + inline void writeInt64Little(atInt64 val) + { + utility::LittleInt64(val); + writeUBytes((atUint8*)&val, 8); + } + inline void writeValLittle(atInt64 val) {return writeInt64Little(val);} + + inline void writeInt64Big(atInt64 val) + { + utility::BigInt64(val); + writeUBytes((atUint8*)&val, 8); + } + inline void writeValBig(atInt64 val) {return writeInt64Big(val);} + /*! \brief Writes an Uint64 to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -174,6 +228,12 @@ public: inline void writeUint64(atUint64 val) {writeInt64(val);} inline void writeVal(atUint64 val) {return writeUint64(val);} + inline void writeUint64Little(atUint64 val) {writeInt64Little(val);} + inline void writeValLittle(atUint64 val) {return writeUint64Little(val);} + + inline void writeUint64Big(atUint64 val) {writeInt64Big(val);} + inline void writeValBig(atUint64 val) {return writeUint64Big(val);} + /*! \brief Writes an float to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -190,6 +250,20 @@ public: } inline void writeVal(float val) {return writeFloat(val);} + inline void writeFloatLittle(float val) + { + utility::LittleFloat(val); + writeUBytes((atUint8*)&val, 4); + } + inline void writeValLittle(float val) {return writeFloatLittle(val);} + + inline void writeFloatBig(float val) + { + utility::BigFloat(val); + writeUBytes((atUint8*)&val, 4); + } + inline void writeValBig(float val) {return writeFloatBig(val);} + /*! \brief Writes an double to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -206,6 +280,20 @@ public: } inline void writeVal(double val) {return writeDouble(val);} + inline void writeDoubleLittle(double val) + { + utility::LittleDouble(val); + writeUBytes((atUint8*)&val, 8); + } + inline void writeValLittle(double val) {return writeDoubleLittle(val);} + + inline void writeDoubleBig(double val) + { + utility::BigDouble(val); + writeUBytes((atUint8*)&val, 8); + } + inline void writeValBig(double val) {return writeDoubleBig(val);} + /*! \brief Writes an bool to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -237,6 +325,22 @@ public: } inline void writeVal(atVec2f val) {return writeVec2f(val);} + inline void writeVec2fLittle(atVec2f vec) + { + utility::LittleFloat(vec.vec[0]); + utility::LittleFloat(vec.vec[1]); + writeUBytes((atUint8*)&vec, 8); + } + inline void writeValLittle(atVec2f val) {return writeVec2fLittle(val);} + + inline void writeVec2fBig(atVec2f vec) + { + utility::BigFloat(vec.vec[0]); + utility::BigFloat(vec.vec[1]); + writeUBytes((atUint8*)&vec, 8); + } + inline void writeValBig(atVec2f val) {return writeVec2fBig(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. * @@ -261,6 +365,24 @@ public: } inline void writeVal(atVec3f val) {return writeVec3f(val);} + inline void writeVec3fLittle(atVec3f vec) + { + utility::LittleFloat(vec.vec[0]); + utility::LittleFloat(vec.vec[1]); + utility::LittleFloat(vec.vec[2]); + writeUBytes((atUint8*)&vec, 12); + } + inline void writeValLittle(atVec3f val) {return writeVec3fLittle(val);} + + inline void writeVec3fBig(atVec3f vec) + { + utility::BigFloat(vec.vec[0]); + utility::BigFloat(vec.vec[1]); + utility::BigFloat(vec.vec[2]); + writeUBytes((atUint8*)&vec, 12); + } + inline void writeValBig(atVec3f val) {return writeVec3fBig(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. * @@ -287,6 +409,26 @@ public: } inline void writeVal(atVec4f val) {return writeVec4f(val);} + inline void writeVec4fLittle(atVec4f vec) + { + utility::LittleFloat(vec.vec[0]); + utility::LittleFloat(vec.vec[1]); + utility::LittleFloat(vec.vec[2]); + utility::LittleFloat(vec.vec[3]); + writeUBytes((atUint8*)&vec, 16); + } + inline void writeValLittle(atVec4f val) {return writeVec4fLittle(val);} + + inline void writeVec4fBig(atVec4f vec) + { + utility::BigFloat(vec.vec[0]); + utility::BigFloat(vec.vec[1]); + utility::BigFloat(vec.vec[2]); + utility::BigFloat(vec.vec[3]); + writeUBytes((atUint8*)&vec, 16); + } + inline void writeValBig(atVec4f val) {return writeVec4fBig(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. * @@ -332,6 +474,82 @@ public: } } + inline void writeStringAsWStringLittle(const std::string& str, atInt32 fixedLen = -1) + { + std::string tmpStr = "\xEF\xBB\xBF" + str; + + std::wstring_convert> conv; + std::wstring tmp = conv.from_bytes(tmpStr); + + if (fixedLen < 0) + { + for (atUint16 chr : tmp) + { + if (chr != 0xFEFF) + writeUint16Little(chr); + } + writeUint16Little(0); + } + else + { + auto it = tmp.begin(); + for (atInt32 i=0 ; i> conv; + std::wstring tmp = conv.from_bytes(tmpStr); + + if (fixedLen < 0) + { + for (atUint16 chr : tmp) + { + if (chr != 0xFEFF) + writeUint16Big(chr); + } + writeUint16Big(0); + } + else + { + auto it = tmp.begin(); + for (atInt32 i=0 ; i + void enumerateLittle(const std::vector& vector, + typename std::enable_if::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) + { + for (const T& item : vector) + writeValLittle(item); + } + + template + void enumerateBig(const std::vector& vector, + typename std::enable_if::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) + { + for (const T& item : vector) + writeValBig(item); + } + template void enumerate(const std::vector& vector, typename std::enable_if::value &&