From 8dc86ea991d6c647faa10043afc88f520443575f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 4 Sep 2019 15:18:26 -0400 Subject: [PATCH 01/21] main: Amend inclusion order --- atdna/main.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index 3f3ad92..2a8af6e 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -1,19 +1,22 @@ +#include #include -#include -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Frontend/Utils.h" -#include "clang/Tooling/Tooling.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Sema/Sema.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/TypeLoc.h" -#include "clang/Basic/Version.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/CommandLine.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include using namespace std::literals; From 607f99fa1afba646d706c43fa60cc674658a2d01 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 4 Sep 2019 15:23:44 -0400 Subject: [PATCH 02/21] main: Amend variable shadowing warnings --- atdna/main.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index 2a8af6e..9c12106 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -137,15 +137,15 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { const auto* vType = static_cast(field->getType().getTypePtr()); if (vType->isVectorType()) { const auto* eType = static_cast(vType->getElementType().getTypePtr()); - const uint64_t width = context.getTypeInfo(eType).Width; - if (!eType->isBuiltinType() || !eType->isFloatingPoint() || (width != 32 && width != 64)) + const uint64_t typeWidth = context.getTypeInfo(eType).Width; + if (!eType->isBuiltinType() || !eType->isFloatingPoint() || (typeWidth != 32 && typeWidth != 64)) continue; if (vType->getNumElements() == 2) { - return width / 8 * 2; + return typeWidth / 8 * 2; } else if (vType->getNumElements() == 3) { - return width / 8 * 3; + return typeWidth / 8 * 3; } else if (vType->getNumElements() == 4) { - return width / 8 * 4; + return typeWidth / 8 * 4; } } } @@ -687,18 +687,18 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } else { const clang::NamedDecl* nd = tsDecl->getTemplatedDecl(); if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null(nd)) { - std::string baseDNA; - if (isDNARecord(rd, baseDNA)) + std::string baseDNA2; + if (isDNARecord(rd, baseDNA2)) { outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); + } } } - } - - else if (regType->getTypeClass() == clang::Type::Record) { + } else if (regType->getTypeClass() == clang::Type::Record) { const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - std::string baseDNA; - if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) + std::string baseDNA2; + if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) { outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); + } } } @@ -995,20 +995,18 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } else { const clang::NamedDecl* nd = tsDecl->getTemplatedDecl(); if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null(nd)) { - std::string baseDNA; - if (isDNARecord(rd, baseDNA)) { + std::string baseDNA2; + if (isDNARecord(rd, baseDNA2)) { fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" << " return true;\n"; } } } - } - - else if (regType->getTypeClass() == clang::Type::Record) { + } else if (regType->getTypeClass() == clang::Type::Record) { const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - std::string baseDNA; - if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) { + std::string baseDNA2; + if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) { fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" << " return true;\n"; From 0dcf0cec03ad6bdd1e137175ed9ad02d1d1da5ce Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 4 Sep 2019 15:28:00 -0400 Subject: [PATCH 03/21] main: Avoid unnecessary string churn Reduces the amount of overall allocation churn due to string concatenation by avoiding redundant string temporaries. --- atdna/main.cpp | 169 +++++++++++++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 70 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index 9c12106..e1cb6ec 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -167,7 +167,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { static std::string GetPropIdExpr(const clang::FieldDecl* field, const std::string& fieldName) { std::string fieldStr = GetFieldString(fieldName); - std::string propIdExpr = "\"" + fieldStr + "\""; + std::string propIdExpr = "\""s.append(fieldStr).append(1, '\"'); for (clang::Attr* attr : field->attrs()) { if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) { llvm::StringRef textRef = annot->getAnnotation(); @@ -187,22 +187,39 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& endianExpr) { - return "(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", s)"; + return "(athena::io::PropId(") + .append(propIdExpr) + .append("), ") + .append(fieldName) + .append(", s)"); } static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) { - return "(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", s)"; + return "(athena::io::PropId("s.append(propIdExpr).append("), ").append(fieldName).append(", s)"); } static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr, const std::string& endianExpr) { - return "(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", " + sizeExpr + ", s)"; + return "(athena::io::PropId(") + .append(propIdExpr) + .append("), ") + .append(fieldName) + .append(", ") + .append(sizeExpr) + .append(", s)"); } static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr) { - return "(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", " + sizeExpr + ", s)"; + return "(athena::io::PropId("s.append(propIdExpr) + .append("), ") + .append(fieldName) + .append(", ") + .append(sizeExpr) + .append(", s)"); } static void RecurseNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) { @@ -223,7 +240,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { templateStmt += ", "; qualType += ", "; } - templateStmt += "class "s + tpParm->getName().data(); + templateStmt += "class "s.append(tpParm->getName().str()); qualType += tpParm->getName(); needsComma = true; } else if (const clang::NonTypeTemplateParmDecl* nonTypeParm = @@ -232,7 +249,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { templateStmt += ", "; qualType += ", "; } - templateStmt += nonTypeParm->getType().getAsString() + ' ' + nonTypeParm->getName().data(); + templateStmt += nonTypeParm->getType().getAsString().append(1, ' ').append(nonTypeParm->getName().str()); qualType += nonTypeParm->getName(); needsComma = true; } @@ -280,10 +297,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { int numTuples = int(specParms.size()) / numParms; for (const auto& parent : parentSpecializations) { for (int i = 0; i < numTuples; ++i) { - if (parent.first.empty()) - specializations.emplace_back(std::string(rec->getName().data()) + '<', 1); - else - specializations.emplace_back(parent.first + "::" + rec->getName().data() + '<', parent.second + 1); + if (parent.first.empty()) { + specializations.emplace_back(std::string(rec->getName().str()).append(1, '<'), 1); + } else { + auto specialization = + std::string(parent.first).append("::").append(rec->getName().str()).append(1, '<'); + specializations.emplace_back(std::move(specialization), parent.second + 1); + } bool needsComma = false; for (auto it = specParms.begin() + i * numParms; it != specParms.end() && it != specParms.begin() + (i + 1) * numParms; ++it) { @@ -293,7 +313,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { specializations.back().first += trimmed; needsComma = true; } - specializations.back().first += ">"; + specializations.back().first += '>'; } } foundSpecializations = true; @@ -304,16 +324,20 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } } - if (!foundSpecializations) + if (!foundSpecializations) { for (const auto& parent : parentSpecializations) { if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null(decl)) { - if (parent.first.empty()) - specializations.emplace_back(namedDecl->getName().data(), parent.second); - else - specializations.emplace_back(parent.first + "::" + namedDecl->getName().data(), parent.second); - } else + if (parent.first.empty()) { + specializations.emplace_back(namedDecl->getName().str(), parent.second); + } else { + specializations.emplace_back(std::string(parent.first).append("::").append(namedDecl->getName().str()), + parent.second); + } + } else { specializations.push_back(parent); + } } + } } static std::vector> GetNestedTypeSpecializations(const clang::DeclContext* decl) { @@ -339,8 +363,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { std::string m_fieldName; std::string m_ioOp; bool m_squelched = false; - OutputNode(NodeType type, const std::string& fieldName, const std::string& ioOp, bool squelched) - : m_type(type), m_fieldName(fieldName), m_ioOp(ioOp), m_squelched(squelched) {} + OutputNode(NodeType type, std::string fieldName, std::string ioOp, bool squelched) + : m_type(type), m_fieldName(std::move(fieldName)), m_ioOp(std::move(ioOp)), m_squelched(squelched) {} }; std::vector outputNodes; @@ -392,24 +416,24 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } std::string ioOp; - bool isDNAType = false; for (const clang::TemplateArgument& arg : *tsType) { if (arg.getKind() == clang::TemplateArgument::Type) { - if (defaultEndian) + if (defaultEndian) { ioOp = GetOpString(fieldName, propIdExpr); - else + } else { ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); + } } } if (ioOp.empty()) { clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena"); + diag.AddString("Unable to use type '"s.append(tsDecl->getName().str()).append("' with Athena")); diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); continue; } - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); } else if (!tsDecl->getName().compare("Vector")) { llvm::APSInt endian(64, -1); std::string endianExprStr; @@ -460,20 +484,20 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { clang::QualType templateType; std::string ioOp; - bool isDNAType = false; for (const clang::TemplateArgument& arg : *tsType) { if (arg.getKind() == clang::TemplateArgument::Type) { templateType = arg.getAsType().getCanonicalType(); - if (defaultEndian) + if (defaultEndian) { ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); - else + } else { ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); + } } } if (ioOp.empty()) { clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); + diag.AddString("Unable to use type '"s.append(templateType.getAsString()).append("' with Athena")); diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); continue; } @@ -485,7 +509,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { continue; } - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); } else if (!tsDecl->getName().compare("Buffer")) { const clang::Expr* sizeExpr = nullptr; std::string sizeExprStr; @@ -517,8 +541,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); } else if (!tsDecl->getName().compare("String")) { std::string sizeExprStr; for (const clang::TemplateArgument& arg : *tsType) { @@ -540,12 +563,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } std::string ioOp; - if (!sizeExprStr.empty()) + if (!sizeExprStr.empty()) { ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else + } else { ioOp = GetOpString(fieldName, propIdExpr); + } - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); } else if (!tsDecl->getName().compare("WString")) { llvm::APSInt endian(64, -1); std::string endianExprStr; @@ -588,18 +612,20 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { std::string ioOp; if (!sizeExprStr.empty()) { - if (defaultEndian) + if (defaultEndian) { ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else + } else { ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); + } } else { - if (defaultEndian) + if (defaultEndian) { ioOp = GetOpString(fieldName, propIdExpr); - else + } else { ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); + } } - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); } else if (!tsDecl->getName().compare("Seek")) { size_t idx = 0; std::string offsetExprStr; @@ -653,15 +679,16 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { continue; } - if (directionVal == 0) - outputNodes.emplace_back(NodeType::DoSeek, fieldName, "("s + offsetExprStr + ", athena::Begin, s)", - false); - else if (directionVal == 1) - outputNodes.emplace_back(NodeType::DoSeek, fieldName, "("s + offsetExprStr + ", athena::Current, s)", - false); - else if (directionVal == 2) - outputNodes.emplace_back(NodeType::DoSeek, fieldName, "("s + offsetExprStr + ", athena::End, s)", - false); + if (directionVal == 0) { + outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), + "("s.append(offsetExprStr).append(", athena::Begin, s)"), false); + } else if (directionVal == 1) { + outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), + "("s.append(offsetExprStr).append(", athena::Current, s)"), false); + } else if (directionVal == 2) { + outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), + "("s.append(offsetExprStr).append(", athena::End, s)"), false); + } } else if (!tsDecl->getName().compare("Align")) { llvm::APSInt align(64, 0); bool bad = false; @@ -680,16 +707,17 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { if (bad) continue; - int64_t alignVal = align.getSExtValue(); + const int64_t alignVal = align.getSExtValue(); if (alignVal) { - outputNodes.emplace_back(NodeType::DoAlign, fieldName, "("s + align.toString(10, true) + ", s)", false); + outputNodes.emplace_back(NodeType::DoAlign, std::move(fieldName), + "("s.append(align.toString(10, true)).append(", s)"), false); } } else { const clang::NamedDecl* nd = tsDecl->getTemplatedDecl(); if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null(nd)) { std::string baseDNA2; if (isDNARecord(rd, baseDNA2)) { - outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), GetOpString(fieldName, propIdExpr), false); } } } @@ -697,7 +725,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); std::string baseDNA2; if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) { - outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); + outputNodes.emplace_back(NodeType::Do, std::move(fieldName), GetOpString(fieldName, propIdExpr), false); } } } @@ -784,7 +812,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } std::string ioOp; - bool isDNAType = false; for (const clang::TemplateArgument& arg : *tsType) { if (arg.getKind() == clang::TemplateArgument::Type) { if (defaultEndian) @@ -796,7 +823,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { if (ioOp.empty()) { clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena"); + diag.AddString("Unable to use type '"s.append(tsDecl->getName().str()).append("' with Athena")); diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); continue; } @@ -844,7 +871,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { clang::QualType templateType; std::string ioOp; - bool isDNAType = false; for (const clang::TemplateArgument& arg : *tsType) { if (arg.getKind() == clang::TemplateArgument::Type) { templateType = arg.getAsType().getCanonicalType(); @@ -857,7 +883,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { if (ioOp.empty()) { clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); + diag.AddString("Unable to use type '"s.append(templateType.getAsString()).append("' with Athena")); diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); continue; } @@ -1169,24 +1195,27 @@ int main(int argc, const char** argv) { if (Help) llvm::cl::PrintHelpMessage(); - std::vector args = {"clang-tool", + std::vector args = { + "clang-tool", #ifdef __linux__ - "--gcc-toolchain=/usr", + "--gcc-toolchain=/usr", #endif - "-fsyntax-only", - "-std=c++1z", - "-D__atdna__=1", - "-Wno-expansion-to-defined", - "-Wno-nullability-completeness", - "-Werror=shadow-field", - "-I" XSTR(INSTALL_PREFIX) "/lib/clang/" CLANG_VERSION_STRING "/include", - "-I" XSTR(INSTALL_PREFIX) "/include/Athena"}; - for (int a = 1; a < argc; ++a) - args.push_back(argv[a]); + "-fsyntax-only", + "-std=c++1z", + "-D__atdna__=1", + "-Wno-expansion-to-defined", + "-Wno-nullability-completeness", + "-Werror=shadow-field", + "-I" XSTR(INSTALL_PREFIX) "/lib/clang/" CLANG_VERSION_STRING "/include", + "-I" XSTR(INSTALL_PREFIX) "/include/Athena", + }; + for (int a = 1; a < argc; ++a) { + args.emplace_back(argv[a]); + } llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); ATDNAAction* action = new ATDNAAction(); - clang::tooling::ToolInvocation TI(args, action, fman.get()); + clang::tooling::ToolInvocation TI(std::move(args), action, fman.get()); if (!TI.run()) return 1; From 016e14c460e4a0ee928dc3547be787caa2191197 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 5 Sep 2019 01:12:05 -0400 Subject: [PATCH 04/21] MemoryWriter: Initialize member variables to deterministic values Makes the variable initialization behavior deterministic in the case of the default constructor. This also eliminates the possibility of an uninitialized read from occurring within the destructor entirely; even in the face of future changes. --- include/athena/MemoryWriter.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/athena/MemoryWriter.hpp b/include/athena/MemoryWriter.hpp index c9306d0..c3e87da 100644 --- a/include/athena/MemoryWriter.hpp +++ b/include/athena/MemoryWriter.hpp @@ -90,11 +90,11 @@ public: void writeUBytes(const atUint8* data, atUint64 length) override; protected: - MemoryWriter() {} - atUint8* m_data; - atUint64 m_length; - atUint64 m_position; - bool m_bufferOwned; + MemoryWriter() = default; + atUint8* m_data = nullptr; + atUint64 m_length = 0; + atUint64 m_position = 0; + bool m_bufferOwned = false; std::string m_filepath; //!< Path to the target file }; From 4e414902bec27bc8fb7af476bedf7974c1f35ef9 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 6 Sep 2019 03:23:42 -0400 Subject: [PATCH 05/21] MemoryWriter: Use a std::unique_ptr for FILE handle in save() Prevents potential leaks from occurring within failure cases (e.g. with the default exception handler). --- src/athena/MemoryWriter.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index 4e8bb61..256cbf9 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -185,11 +185,11 @@ void MemoryWriter::save(std::string_view filename) { return; } - if (!filename.empty()) + if (!filename.empty()) { m_filepath = filename; + } - FILE* out = fopen(m_filepath.c_str(), "wb"); - + std::unique_ptr out{std::fopen(m_filepath.c_str(), "wb"), std::fclose}; if (!out) { atError(fmt("Unable to open file '{}'"), m_filepath); setError(); @@ -200,22 +200,24 @@ void MemoryWriter::save(std::string_view filename) { atUint64 blocksize = BLOCKSZ; do { - if (blocksize > m_length - done) + if (blocksize > m_length - done) { blocksize = m_length - done; + } - atInt64 ret = fwrite(m_data + done, 1, blocksize, out); + const atInt64 ret = std::fwrite(m_data + done, 1, blocksize, out.get()); if (ret < 0) { atError(fmt("Error writing data to disk")); setError(); return; - } else if (ret == 0) + } + + if (ret == 0) { break; + } done += blocksize; } while (done < m_length); - - fclose(out); } void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) { From 57ad780321c798f29dfd375e8fc46b7e9de385ec Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 6 Sep 2019 03:25:40 -0400 Subject: [PATCH 06/21] MemoryWriter: Remove unnecessary type cast within MemoryWriter constructor and setData() The input type is already the same type as the class member, so the cast is unnecessary. While we're at it, we can also remove an unnecessary initializer for m_position, since we initialize this to zero within the class declaration already. --- src/athena/MemoryWriter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index 256cbf9..a7e3c68 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -10,7 +10,7 @@ namespace athena::io { MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership) -: m_data((atUint8*)data), m_length(length), m_position(0), m_bufferOwned(takeOwnership) { +: m_data(data), m_length(length), m_bufferOwned(takeOwnership) { if (!data) { atError(fmt("data cannot be NULL")); setError(); @@ -156,7 +156,7 @@ void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) { if (m_bufferOwned) delete m_data; - m_data = (atUint8*)data; + m_data = data; m_length = length; m_position = 0; m_bufferOwned = takeOwnership; From de45f0896feeb257b2a6d9b41fdbab9ddadb3cfb Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 6 Sep 2019 03:28:29 -0400 Subject: [PATCH 07/21] MemoryWriter: Use a std::unique_ptr within resize() Same behavior, but keeps the memory managed throughout its whole lifetime. --- src/athena/MemoryWriter.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index a7e3c68..607a964 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -260,15 +260,14 @@ void MemoryCopyWriter::resize(atUint64 newSize) { } // Allocate and copy new buffer - atUint8* newArray = new atUint8[newSize]; - memset(newArray, 0, newSize); - - if (m_dataCopy) - memmove(newArray, m_dataCopy.get(), m_length); - m_dataCopy.reset(newArray); + auto newArray = std::make_unique(newSize); + if (m_dataCopy) { + std::memmove(newArray.get(), m_dataCopy.get(), m_length); + } + m_dataCopy = std::move(newArray); // Swap the pointer and size out for the new ones. - m_data = newArray; + m_data = m_dataCopy.get(); m_length = newSize; } From 200f8f311a1b5ca0d85254c756696be97efb46f7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 6 Sep 2019 03:36:42 -0400 Subject: [PATCH 08/21] Compression/LZ77: Remove unnecessary pointer casts There's no need to cast here in a few of these areas, so we can remove them. This also resolves quite a few -Wcast-qual warnings, --- src/LZ77/LZType10.cpp | 79 +++++++++++++----------- src/LZ77/LZType11.cpp | 122 +++++++++++++++++++------------------ src/athena/Compression.cpp | 3 +- 3 files changed, 109 insertions(+), 95 deletions(-) diff --git a/src/LZ77/LZType10.cpp b/src/LZ77/LZType10.cpp index ee033a9..5b57200 100644 --- a/src/LZ77/LZType10.cpp +++ b/src/LZ77/LZType10.cpp @@ -1,7 +1,12 @@ -#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZType10.hpp" -#include + +#include #include +#include + +#include "LZ77/LZLookupTable.hpp" + +#include LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize) : LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) { @@ -17,25 +22,25 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe athena::io::MemoryCopyWriter outbuf("tmp"); outbuf.writeUint32(encodeSize); - atUint8* ptrStart = (atUint8*)src; - atUint8* ptrEnd = (atUint8*)(src + srcLength); + const atUint8* ptrStart = src; + const atUint8* ptrEnd = src + srcLength; // At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be // compressed it would take blockSize*2 bytes - atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written + auto compressedBytes = std::unique_ptr(new atUint8[m_blockSize * 2]); // Holds the compressed bytes yet to be written while (ptrStart < ptrEnd) { atUint8 blockLen = 0; // In Binary represents 1 if byte is compressed or 0 if not compressed // For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed - atUint8* ptrBytes = compressedBytes; + atUint8* ptrBytes = compressedBytes.get(); for (atInt32 i = 0; i < m_blockSize; i++) { // length_offset searchResult=Search(ptrStart, filedata, ptrEnd); - LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); + const LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); // If the number of bytes to be compressed is at least the size of the Minimum match - if (searchResult.length >= (atUint32)m_minMatch) { + if (searchResult.length >= static_cast(m_minMatch)) { // Gotta swap the bytes since system is wii is big endian and most computers are little endian atUint16 lenOff = (((searchResult.length - m_minMatch) & 0xF) << 12) | ((searchResult.offset - 1) & 0xFFF); athena::utility::BigUint16(lenOff); @@ -49,45 +54,50 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe blockLen |= (1 << (7 - i)); // Stores which of the next 8 bytes is compressed // bit 1 for compress and bit 0 for not compressed - } else + } else { *ptrBytes++ = *ptrStart++; + } } outbuf.writeByte(blockLen); - outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + outbuf.writeUBytes(compressedBytes.get(), static_cast(ptrBytes - compressedBytes.get())); } - delete[] compressedBytes; - compressedBytes = nullptr; - // Add zeros until the file is a multiple of 4 - while ((outbuf.position() % 4) != 0) + while ((outbuf.position() % 4) != 0) { outbuf.writeByte(0); + } *dstBuf = outbuf.data(); outbuf.save(); - return (atUint32)outbuf.length(); + return static_cast(outbuf.length()); } atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) { - if (*(atUint8*)(src) != 0x10) + if (*src != 0x10) { return 0; + } - atUint32 uncompressedSize = *(atUint32*)(src); // Size of data when it is uncompressed - athena::utility::LittleUint32(uncompressedSize); // The compressed file has the filesize encoded in little endian - uncompressedSize = uncompressedSize >> 8; // first byte is the encode flag + // Size of data when it is uncompressed + atUint32 uncompressedSize; + std::memcpy(&uncompressedSize, src, sizeof(uncompressedSize)); - atUint8* uncompressedData = new atUint8[uncompressedSize]; - atUint8* outputPtr = uncompressedData; - atUint8* outputEndPtr = uncompressedData + uncompressedSize; - atUint8* inputPtr = (atUint8*)src + 4; - atUint8* inputEndPtr = (atUint8*)src + srcLength; + // The compressed file has the filesize encoded in little endian + athena::utility::LittleUint32(uncompressedSize); + + // first byte is the encode flag + uncompressedSize = uncompressedSize >> 8; + + auto uncompressedData = std::unique_ptr(new atUint8[uncompressedSize]); + atUint8* outputPtr = uncompressedData.get(); + atUint8* outputEndPtr = uncompressedData.get() + uncompressedSize; + const atUint8* inputPtr = src + 4; + const atUint8* inputEndPtr = src + srcLength; while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) { + const atUint8 isCompressed = *inputPtr++; - atUint8 isCompressed = *inputPtr++; - - for (atUint32 i = 0; i < (atUint32)m_blockSize; i++) { + for (atUint32 i = 0; i < static_cast(m_blockSize); i++) { // Checks to see if the next byte is compressed by looking // at its binary representation - E.g 10010000 // This says that the first extracted byte and the four extracted byte is compressed @@ -101,28 +111,29 @@ atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLen decoding.length = (lenOff >> 12) + m_minMatch; decoding.offset = static_cast((lenOff & 0xFFF) + 1); - if ((outputPtr - decoding.offset) < uncompressedData) { + if ((outputPtr - decoding.offset) < uncompressedData.get()) { // If the offset to look for uncompressed is passed the current uncompresed data then the data is not // compressed - delete[] uncompressedData; - uncompressedData = nullptr; dst = nullptr; return 0; } - for (atUint32 j = 0; j < decoding.length; ++j) + for (size_t j = 0; j < decoding.length; ++j) { outputPtr[j] = (outputPtr - decoding.offset)[j]; + } outputPtr += decoding.length; - } else + } else { *outputPtr++ = *inputPtr++; + } - if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) + if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) { break; + } } } - *dst = uncompressedData; + *dst = uncompressedData.release(); return uncompressedSize; } diff --git a/src/LZ77/LZType11.cpp b/src/LZ77/LZType11.cpp index de26bd8..912c71b 100644 --- a/src/LZ77/LZType11.cpp +++ b/src/LZ77/LZType11.cpp @@ -1,7 +1,12 @@ -#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZType11.hpp" -#include + +#include #include +#include + +#include "LZ77/LZLookupTable.hpp" + +#include LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) : LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) { @@ -12,32 +17,32 @@ LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimum atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) { athena::io::MemoryCopyWriter outbuff("tmp"); - if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs - { + if (srcLength > 0xFFFFFF) { // If length is greater than 24 bits or 16 Megs atUint32 encodeFlag = 0x11; athena::utility::LittleUint32(encodeFlag); athena::utility::LittleUint32(srcLength); // Filesize data is little endian outbuff.writeUint32(encodeFlag); outbuff.writeUint32(srcLength); - } else { atUint32 encodeSize = (srcLength << 8) | (0x11); athena::utility::LittleUint32(encodeSize); outbuff.writeUint32(encodeSize); } - atUint8* ptrStart = (atUint8*)src; - atUint8* ptrEnd = (atUint8*)(src + srcLength); + const atUint8* ptrStart = src; + const atUint8* ptrEnd = src + srcLength; // At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be // compressed it would take blockSize*2 bytes - atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written - atUint8 maxTwoByteMatch = 0xF + 1; - atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1 - atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch; - atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1 - atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch; + // Holds the compressed bytes yet to be written + auto compressedBytes = std::unique_ptr(new atUint8[m_blockSize * 2]); + + const atUint8 maxTwoByteMatch = 0xF + 1; + const atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1 + const atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch; + const atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1 + const atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch; /* Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15. @@ -57,14 +62,14 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt atUint8 blockSize = 0; // In Binary represents 1 if byte is compressed or 0 if not compressed // For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed - atUint8* ptrBytes = compressedBytes; + atUint8* ptrBytes = compressedBytes.get(); for (atInt32 i = 0; i < m_blockSize; i++) { // length_offset searchResult=Search(filedata,ptrStart,ptrEnd); - LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); + const LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); // If the number of bytes to be compressed is at least the size of the Minimum match - if (searchResult.length >= (atUint32)m_minMatch) { + if (searchResult.length >= static_cast(m_minMatch)) { // Gotta swap the bytes since system is wii is big endian and most computers are little endian if (searchResult.length <= maxTwoByteMatch) { @@ -79,10 +84,10 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt ((searchResult.offset - 1) & 0xFFF) // Bits 11-0 ); athena::utility::BigUint32(lenOff); - memcpy(ptrBytes, (atUint8*)&lenOff + 1, + memcpy(ptrBytes, reinterpret_cast(&lenOff) + 1, 3); // Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456 ptrBytes += 3; - } else if (searchResult.length <= (atUint32)maxFourByteMatch) { + } else if (searchResult.length <= static_cast(maxFourByteMatch)) { atUint32 lenOff = ((1 << 28) | // Bits 31-28 Flag to say that this is four bytes (((searchResult.length - minFourByteMatch) & 0xFFFF) << 12) | // Bits 28-12 ((searchResult.offset - 1) & 0xFFF) // Bits 11-0 @@ -97,83 +102,80 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt blockSize |= (1 << (7 - i)); // Stores which of the next 8 bytes is compressed // bit 1 for compress and bit 0 for not compressed - } else + } else { *ptrBytes++ = *ptrStart++; + } } outbuff.writeByte(blockSize); - outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + outbuff.writeUBytes(compressedBytes.get(), static_cast(ptrBytes - compressedBytes.get())); } - delete[] compressedBytes; - compressedBytes = nullptr; - // Add zeros until the file is a multiple of 4 - while ((outbuff.position() % 4) != 0) + while ((outbuff.position() % 4) != 0) { outbuff.writeByte(0); + } *dst = outbuff.data(); - return (atUint32)outbuff.length(); + return static_cast(outbuff.length()); } atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) { - if (*(atUint8*)(src) != 0x11) + if (*src != 0x11) { return 0; + } - atUint32 uncompressedLen = *(atUint32*)(src); + atUint32 uncompressedLen; + std::memcpy(&uncompressedLen, src, sizeof(uncompressedLen)); athena::utility::LittleUint32(uncompressedLen); // The compressed file has the filesize encoded in little endian uncompressedLen = uncompressedLen >> 8; // First byte is the encode flag atUint32 currentOffset = 4; - if (uncompressedLen == - 0) // If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes - { - atUint32 filesize = *(atUint32*)(src + 4); + // If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes + if (uncompressedLen == 0) { + atUint32 filesize; + std::memcpy(&filesize, src + 4, sizeof(filesize)); filesize = athena::utility::LittleUint32(filesize); currentOffset += 4; } - atUint8* uncompressedData = new atUint8[uncompressedLen]; - atUint8* outputPtr = uncompressedData; - atUint8* outputEndPtr = uncompressedData + uncompressedLen; - atUint8* inputPtr = (atUint8*)src + currentOffset; - atUint8* inputEndPtr = (atUint8*)src + srcLength; + auto uncompressedData = std::unique_ptr(new atUint8[uncompressedLen]); + atUint8* outputPtr = uncompressedData.get(); + atUint8* outputEndPtr = uncompressedData.get() + uncompressedLen; + const atUint8* inputPtr = src + currentOffset; + const atUint8* inputEndPtr = src + srcLength; LZLengthOffset decoding; - atUint8 maxTwoByteMatch = 0xF + 1; - atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes - atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm; - atUint16 fourByteDenorm = maxThreeByteMatch + 1; + const atUint8 maxTwoByteMatch = 0xF + 1; + const atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes + const atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm; + const atUint16 fourByteDenorm = maxThreeByteMatch + 1; while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) { - - atUint8 isCompressed = *inputPtr++; + const atUint8 isCompressed = *inputPtr++; for (atInt32 i = 0; i < m_blockSize; i++) { // Checks to see if the next byte is compressed by looking // at its binary representation - E.g 10010000 // This says that the first extracted byte and the four extracted byte is compressed if ((isCompressed >> (7 - i)) & 0x1) { - atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits + const atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits - if (metaDataSize >= 2) // Two Bytes of Length/Offset MetaData - { + if (metaDataSize >= 2) { // Two Bytes of Length/Offset MetaData atUint16 lenOff = 0; memcpy(&lenOff, inputPtr, 2); inputPtr += 2; athena::utility::BigUint16(lenOff); decoding.length = (lenOff >> 12) + 1; decoding.offset = (lenOff & 0xFFF) + 1; - } else if (metaDataSize == 0) // Three Bytes of Length/Offset MetaData - { + } else if (metaDataSize == 0) { // Three Bytes of Length/Offset MetaData atUint32 lenOff = 0; - memcpy((atUint8*)&lenOff + 1, inputPtr, 3); + memcpy(reinterpret_cast(&lenOff) + 1, inputPtr, 3); inputPtr += 3; athena::utility::BigUint32(lenOff); decoding.length = (lenOff >> 12) + threeByteDenorm; decoding.offset = (lenOff & 0xFFF) + 1; - } else if (metaDataSize == 1) // Four Bytes of Length/Offset MetaData - { + } else if (metaDataSize == 1) { // Four Bytes of Length/Offset MetaData atUint32 lenOff = 0; memcpy(&lenOff, inputPtr, 4); inputPtr += 4; @@ -182,30 +184,30 @@ atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLen decoding.length = ((lenOff >> 12) & 0xFFFF) + fourByteDenorm; // Gets rid of the Four byte flag decoding.offset = (lenOff & 0xFFF) + 1; } else { - delete[] uncompressedData; - uncompressedData = nullptr; return 0; } - if ((outputPtr - decoding.offset) < uncompressedData) // If the offset to look for uncompressed is passed the - // current uncompresed data then the data is not compressed - { - delete[] uncompressedData; + // If the offset to look for uncompressed is passed the + // current uncompresed data then the data is not compressed + if ((outputPtr - decoding.offset) < uncompressedData.get()) { return 0; } - for (atUint32 j = 0; j < decoding.length; ++j) + for (size_t j = 0; j < decoding.length; ++j) { outputPtr[j] = (outputPtr - decoding.offset)[j]; + } outputPtr += decoding.length; - } else + } else { *outputPtr++ = *inputPtr++; + } - if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) + if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) { break; + } } } - *dst = uncompressedData; + *dst = uncompressedData.release(); return uncompressedLen; } diff --git a/src/athena/Compression.cpp b/src/athena/Compression.cpp index 2f7ac54..4ede938 100644 --- a/src/athena/Compression.cpp +++ b/src/athena/Compression.cpp @@ -303,8 +303,9 @@ atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMat } atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) { - if (*(atUint8*)src == 0x11) + if (*src == 0x11) { return LZType11().decompress(src, dst, srcLen); + } return LZType10(2).decompress(src, dst, srcLen); } From 34ae45bbd14019fcdb1178e3ddd3238b860cc018 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 6 Sep 2019 04:46:25 -0400 Subject: [PATCH 09/21] Checksums: Correct null check within crc16 This should be checking if the input is null rather than not null before early exiting, otherwise the data itself will never have the checksum calculated. --- src/athena/Checksums.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/athena/Checksums.cpp b/src/athena/Checksums.cpp index 2f69ece..a3ee6cc 100644 --- a/src/athena/Checksums.cpp +++ b/src/athena/Checksums.cpp @@ -145,8 +145,9 @@ atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint1 } atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) { - if (data) + if (data == nullptr) { return seed; + } static const atUint16 crc16Table[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, From 462146b644a7083efe817c86c3fc99c8c59fbc62 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 07:54:08 -0400 Subject: [PATCH 10/21] FileWriterWin32: Prevent implicit sign conversion within position() --- src/athena/FileWriterWin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp index 9a6cd43..684927d 100644 --- a/src/athena/FileWriterWin32.cpp +++ b/src/athena/FileWriterWin32.cpp @@ -89,7 +89,7 @@ atUint64 FileWriter::position() const { LARGE_INTEGER li = {}; LARGE_INTEGER res; SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); - return res.QuadPart; + return static_cast(res.QuadPart); } atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } From 3b1348a26a2235d192ae185609aacd6e124bc660 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 07:55:23 -0400 Subject: [PATCH 11/21] FileWriterWin32: Handle large files within writeUBytes Handles the case where a given size exceeds the maximum value that can be contained within a DWORD. Given a DWORD is 32-bit in size and an atUint64 is 64-bits in size, this avoids errors on valid sizes, even if they're extremely unlikely to ever occur. --- src/athena/FileWriterWin32.cpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp index 684927d..7e2d117 100644 --- a/src/athena/FileWriterWin32.cpp +++ b/src/athena/FileWriterWin32.cpp @@ -1,5 +1,10 @@ #include "athena/FileWriter.hpp" -#include "win32_largefilewrapper.h" + +#include +#include + +#undef min +#undef max namespace athena::io { FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) @@ -96,19 +101,29 @@ atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } void FileWriter::writeUBytes(const atUint8* data, atUint64 len) { if (!isOpen()) { - if (m_globalErr) + if (m_globalErr) { atError(fmt("File not open for writing")); + } setError(); return; } - DWORD ret = 0; - WriteFile(m_fileHandle, data, len, &ret, nullptr); - if (ret != len) { - if (m_globalErr) - atError(fmt("Unable to write to stream")); - setError(); - } + atUint64 remaining = len; + do { + const auto toWrite = static_cast(std::min(remaining, atUint64{std::numeric_limits::max()})); + DWORD written = 0; + + if (WriteFile(m_fileHandle, data, toWrite, &written, nullptr) == FALSE) { + if (m_globalErr) { + atError(fmt("Unable to write to file")); + } + setError(); + return; + } + + remaining -= written; + data += written; + } while (remaining != 0); } } // namespace athena::io From 4460ecedd2cc8505cad23f98dad8fe7efcfb9a8f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 08:53:03 -0400 Subject: [PATCH 12/21] CMakeLists: Append sources to athena-core directly Avoids using an intermediary variable for the same behavior. --- CMakeLists.txt | 53 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 908be97..43f944a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,19 +19,6 @@ set(ATHENA_VERSION add_subdirectory(extern) -if(WIN32) -list(APPEND CORE_EXTRA src/win32_largefilewrapper.c include/win32_largefilewrapper.h - src/athena/FileWriterWin32.cpp src/athena/FileReaderWin32.cpp) -else() -list(APPEND CORE_EXTRA src/athena/FileWriterNix.cpp src/athena/FileReader.cpp) -if(APPLE OR GEKKO OR NX OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") -list(APPEND CORE_EXTRA src/osx_largefilewrapper.c include/osx_largefilewrapper.h) -if(GEKKO OR NX) -list(APPEND CORE_EXTRA src/gekko_support.c include/gekko_support.h) -endif() -endif() -endif() - add_library(athena-core src/athena/Utility.cpp src/athena/MemoryReader.cpp @@ -49,7 +36,6 @@ add_library(athena-core src/athena/FileInfo.cpp src/athena/Dir.cpp src/athena/DNAYaml.cpp - ${CORE_EXTRA} include/athena/IStream.hpp include/athena/IStreamReader.hpp @@ -81,10 +67,41 @@ add_library(athena-core include/yaml.h include/utf8proc.h ) +if(WIN32) + target_sources(athena-core PRIVATE + src/win32_largefilewrapper.c + include/win32_largefilewrapper.h + src/athena/FileWriterWin32.cpp + src/athena/FileReaderWin32.cpp + ) +else() + target_sources(athena-core PRIVATE + src/athena/FileWriterNix.cpp + src/athena/FileReader.cpp + ) + if(APPLE OR GEKKO OR NX OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + target_sources(athena-core PRIVATE + src/osx_largefilewrapper.c + include/osx_largefilewrapper.h + ) + + if(GEKKO OR NX) + target_sources(athena-core PRIVATE + src/gekko_support.c + include/gekko_support.h + ) + endif() + endif() +endif() + target_include_directories(athena-core PUBLIC - $ - $) -target_link_libraries(athena-core PUBLIC athena-libyaml fmt) + $ + $ +) +target_link_libraries(athena-core PUBLIC + athena-libyaml + fmt +) add_library(athena-sakura EXCLUDE_FROM_ALL src/athena/Sprite.cpp @@ -129,7 +146,7 @@ add_library(athena-wiisave EXCLUDE_FROM_ALL include/sha1.h ) if(NOT MSVC AND NOT GEKKO AND NOT NX) -set_source_files_properties(src/aes.cpp PROPERTIES COMPILE_FLAGS -maes) + set_source_files_properties(src/aes.cpp PROPERTIES COMPILE_FLAGS -maes) endif() From b7974ffd0175a109b34be3cf8a5d5432384c0a26 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 11:43:31 -0400 Subject: [PATCH 13/21] CMakeLists: Define -DNOMINMAX and -DWIN32_LEAN_AND_MEAN on Windows Avoids needing to explicitly define these in code and also allow external targets to be unaffected by this. --- CMakeLists.txt | 5 +++++ src/athena/FileWriterWin32.cpp | 3 --- src/athena/MemoryReader.cpp | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43f944a..6e2a64a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,11 @@ if(WIN32) src/athena/FileWriterWin32.cpp src/athena/FileReaderWin32.cpp ) + + target_compile_definitions(athena-core PRIVATE + -DNOMINMAX + -DWIN32_LEAN_AND_MEAN + ) else() target_sources(athena-core PRIVATE src/athena/FileWriterNix.cpp diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp index 7e2d117..93fddd3 100644 --- a/src/athena/FileWriterWin32.cpp +++ b/src/athena/FileWriterWin32.cpp @@ -3,9 +3,6 @@ #include #include -#undef min -#undef max - namespace athena::io { FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) : m_fileHandle(0), m_globalErr(globalErr) { diff --git a/src/athena/MemoryReader.cpp b/src/athena/MemoryReader.cpp index 7d86191..3441add 100644 --- a/src/athena/MemoryReader.cpp +++ b/src/athena/MemoryReader.cpp @@ -8,9 +8,6 @@ #include #endif // HW_RVL -#undef min -#undef max - namespace athena::io { MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr) : m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) { From b629d90147aa18e8124eac7539c37fd3f8b41ded Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 12:36:56 -0400 Subject: [PATCH 14/21] Global: Make operator|= and &= for enums constexpr These are allowed to be constexpr since C++14 --- include/athena/Global.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/athena/Global.hpp b/include/athena/Global.hpp index ddf7e72..c0ed274 100644 --- a/include/athena/Global.hpp +++ b/include/athena/Global.hpp @@ -95,12 +95,12 @@ typedef struct stat64 atStat64_t; using T = std::underlying_type_t; \ return type(static_cast(a) & static_cast(b)); \ } \ - inline type& operator|=(type& a, const type& b) { \ + constexpr type& operator|=(type& a, type b) { \ using T = std::underlying_type_t; \ a = type(static_cast(a) | static_cast(b)); \ return a; \ } \ - inline type& operator&=(type& a, const type& b) { \ + constexpr type& operator&=(type& a, type b) { \ using T = std::underlying_type_t; \ a = type(static_cast(a) & static_cast(b)); \ return a; \ From c909e628cc90bc7a519b33fad01eccb8cba3c8f8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 12:39:49 -0400 Subject: [PATCH 15/21] Global: Make enum functions noexcept Allows them to be used within other noexcept constructs. --- include/athena/Global.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/athena/Global.hpp b/include/athena/Global.hpp index c0ed274..502291a 100644 --- a/include/athena/Global.hpp +++ b/include/athena/Global.hpp @@ -87,33 +87,33 @@ typedef struct stat64 atStat64_t; #ifndef ENABLE_BITWISE_ENUM #define ENABLE_BITWISE_ENUM(type) \ - constexpr type operator|(type a, type b) { \ + constexpr type operator|(type a, type b) noexcept { \ using T = std::underlying_type_t; \ return type(static_cast(a) | static_cast(b)); \ } \ - constexpr type operator&(type a, type b) { \ + constexpr type operator&(type a, type b) noexcept { \ using T = std::underlying_type_t; \ return type(static_cast(a) & static_cast(b)); \ } \ - constexpr type& operator|=(type& a, type b) { \ + constexpr type& operator|=(type& a, type b) noexcept { \ using T = std::underlying_type_t; \ a = type(static_cast(a) | static_cast(b)); \ return a; \ } \ - constexpr type& operator&=(type& a, type b) { \ + constexpr type& operator&=(type& a, type b) noexcept { \ using T = std::underlying_type_t; \ a = type(static_cast(a) & static_cast(b)); \ return a; \ } \ - constexpr type operator~(type key) { \ + constexpr type operator~(type key) noexcept { \ using T = std::underlying_type_t; \ return type(~static_cast(key)); \ } \ - constexpr bool True(type key) { \ + constexpr bool True(type key) noexcept { \ using T = std::underlying_type_t; \ return static_cast(key) != 0; \ } \ - constexpr bool False(type key) { \ + constexpr bool False(type key) noexcept { \ using T = std::underlying_type_t; \ return static_cast(key) == 0; \ } From 3ca9bcf12df532b3dda596ea44a8fcc0e628433f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 9 Sep 2019 01:08:39 -0400 Subject: [PATCH 16/21] atdna: Be explicit about the SeekOrigin type --- atdna/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index e1cb6ec..7acd2c2 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -681,13 +681,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { if (directionVal == 0) { outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), - "("s.append(offsetExprStr).append(", athena::Begin, s)"), false); + "("s.append(offsetExprStr).append(", athena::SeekOrigin::Begin, s)"), false); } else if (directionVal == 1) { outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), - "("s.append(offsetExprStr).append(", athena::Current, s)"), false); + "("s.append(offsetExprStr).append(", athena::SeekOrigin::Current, s)"), false); } else if (directionVal == 2) { outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), - "("s.append(offsetExprStr).append(", athena::End, s)"), false); + "("s.append(offsetExprStr).append(", athena::SeekOrigin::End, s)"), false); } } else if (!tsDecl->getName().compare("Align")) { llvm::APSInt align(64, 0); From d5e91ca0fee3e41aba0e7b5688d12f113efe45da Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 9 Sep 2019 20:32:00 -0400 Subject: [PATCH 17/21] General: Be explicit about the SeekOrigin type --- atdna/test.hpp | 2 +- include/athena/DNAOp.hpp | 2 +- include/athena/DNAYaml.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atdna/test.hpp b/atdna/test.hpp index 608c2b1..238fb92 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -60,7 +60,7 @@ struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) TESTFile : p Value arrAltCount; Vector arrayAlt; - Seek<21, Current> seek; + Seek<21, SeekOrigin::Current> seek; Value arrCount2; Vector, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2; diff --git a/include/athena/DNAOp.hpp b/include/athena/DNAOp.hpp index f777863..bb10f83 100644 --- a/include/athena/DNAOp.hpp +++ b/include/athena/DNAOp.hpp @@ -372,7 +372,7 @@ struct Read { } static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) { r.seek(amount, whence); } static void DoAlign(atInt64 amount, StreamT& r) { - r.seek((r.position() + amount - 1) / amount * amount, athena::Begin); + r.seek((r.position() + amount - 1) / amount * amount, athena::SeekOrigin::Begin); } }; #define __READ_S(type, endian) \ diff --git a/include/athena/DNAYaml.hpp b/include/athena/DNAYaml.hpp index 4713b14..e2e4e9d 100644 --- a/include/athena/DNAYaml.hpp +++ b/include/athena/DNAYaml.hpp @@ -116,7 +116,7 @@ bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) { atUint64 pos = fin.position(); yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)YAMLAthenaReader, &fin); bool retval = reader.ValidateClassType(DNASubtype::DNAType()); - fin.seek(pos, athena::Begin); + fin.seek(pos, athena::SeekOrigin::Begin); return retval; } From 71eb4992701973cf7252f5ff7ec788e260f2309d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 9 Sep 2019 20:35:41 -0400 Subject: [PATCH 18/21] General: Be explicit about the Endian type --- atdna/test.hpp | 4 ++-- include/athena/Utility.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atdna/test.hpp b/atdna/test.hpp index 238fb92..f92d211 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -1,7 +1,7 @@ #include using namespace athena; -typedef io::DNA BigDNA; +typedef io::DNA BigDNA; enum ETest : atUint8 { ZERO, ONE, TWO, THREE }; @@ -54,7 +54,7 @@ struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) TESTFile : p Value> nestedTemplate1; Value> nestedTemplate2; - Value arrCount[2]; + Value arrCount[2]; Vector array; Value arrAltCount; diff --git a/include/athena/Utility.hpp b/include/athena/Utility.hpp index 2242626..81e118b 100644 --- a/include/athena/Utility.hpp +++ b/include/athena/Utility.hpp @@ -16,8 +16,8 @@ constexpr bool isSystemBigEndian() { return false; } #else constexpr bool isSystemBigEndian() { return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; } #endif -constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? Big : Little; -constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? Little : Big; +constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? ::athena::Endian::Big : ::athena::Endian::Little; +constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? ::athena::Endian::Little : ::athena::Endian::Big; #if _MSC_VER #define BSWAP_CONSTEXPR inline From 9bde23011f1ce369684d472a0b982c40f3eed1b8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 14 Sep 2019 09:22:14 -0400 Subject: [PATCH 19/21] Global: Make SeekOrigin an enum class Makes the enumeration strongly typed and also allows forward declaring the enumeration type as well. --- atdna/main.cpp | 9 ++++++--- include/athena/Global.hpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index 7acd2c2..5b13d2e 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -629,7 +629,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { } else if (!tsDecl->getName().compare("Seek")) { size_t idx = 0; std::string offsetExprStr; - llvm::APSInt direction(64, 0); + llvm::APSInt direction(64, false); const clang::Expr* directionExpr = nullptr; bool bad = false; for (const clang::TemplateArgument& arg : *tsType) { @@ -649,8 +649,11 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { offsetExprStr = offsetLiteral.toString(10); } } else { - directionExpr = expr; - if (!expr->isIntegerConstantExpr(direction, context)) { + clang::APValue result; + if (expr->isCXX11ConstantExpr(context, &result)) { + directionExpr = expr; + direction = result.getInt(); + } else { clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getExprLoc(), AthenaError); diag.AddString("Unable to use non-constant direction expression in Athena"); diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); diff --git a/include/athena/Global.hpp b/include/athena/Global.hpp index 502291a..1f0f58a 100644 --- a/include/athena/Global.hpp +++ b/include/athena/Global.hpp @@ -123,7 +123,7 @@ namespace athena { namespace error { enum class Level { Message, Warning, Error, Fatal }; } -enum SeekOrigin { Begin, Current, End }; +enum class SeekOrigin { Begin, Current, End }; enum Endian { Little, Big }; From 776cb1d04f385d25ce40f319004f118f3cd68ee2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 23 Sep 2019 18:37:07 -0400 Subject: [PATCH 20/21] General: Make Endian an enum class Makes the type strongly typed and not susceptible to implicit conversions. --- include/athena/Global.hpp | 2 +- include/athena/IStream.hpp | 4 ++-- include/athena/IStreamReader.hpp | 22 +++++++++---------- include/athena/IStreamWriter.hpp | 37 ++++++++++++++++++-------------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/athena/Global.hpp b/include/athena/Global.hpp index 1f0f58a..ef7c72e 100644 --- a/include/athena/Global.hpp +++ b/include/athena/Global.hpp @@ -125,7 +125,7 @@ enum class Level { Message, Warning, Error, Fatal }; } enum class SeekOrigin { Begin, Current, End }; -enum Endian { Little, Big }; +enum class Endian { Little, Big }; namespace io { template diff --git a/include/athena/IStream.hpp b/include/athena/IStream.hpp index 4614184..d8d6de0 100644 --- a/include/athena/IStream.hpp +++ b/include/athena/IStream.hpp @@ -23,9 +23,9 @@ protected: void setError() { m_hasError = true; } bool m_hasError = false; #if __BYTE_ORDER == __BIG_ENDIAN - Endian m_endian = Big; + Endian m_endian = Endian::Big; #else - Endian m_endian = Little; + Endian m_endian = Endian::Little; #endif }; } // namespace athena::io diff --git a/include/athena/IStreamReader.hpp b/include/athena/IStreamReader.hpp index 203ed52..7beebdd 100644 --- a/include/athena/IStreamReader.hpp +++ b/include/athena/IStreamReader.hpp @@ -143,7 +143,7 @@ public: atInt16 readInt16() { atInt16 val = 0; readUBytesToBuf(&val, 2); - return m_endian == Big ? utility::BigInt16(val) : utility::LittleInt16(val); + return m_endian == Endian::Big ? utility::BigInt16(val) : utility::LittleInt16(val); } template atInt16 readVal(std::enable_if_t>* = nullptr) { @@ -229,7 +229,7 @@ public: atInt32 readInt32() { atInt32 val = 0; readUBytesToBuf(&val, 4); - return m_endian == Big ? utility::BigInt32(val) : utility::LittleInt32(val); + return m_endian == Endian::Big ? utility::BigInt32(val) : utility::LittleInt32(val); } template atInt32 readVal(std::enable_if_t>* = nullptr) { @@ -315,7 +315,7 @@ public: atInt64 readInt64() { atInt64 val = 0; readUBytesToBuf(&val, 8); - return m_endian == Big ? utility::BigInt64(val) : utility::LittleInt64(val); + return m_endian == Endian::Big ? utility::BigInt64(val) : utility::LittleInt64(val); } template atInt64 readVal(std::enable_if_t>* = nullptr) { @@ -401,7 +401,7 @@ public: float readFloat() { float val = 0.f; readUBytesToBuf(&val, 4); - return m_endian == Big ? utility::BigFloat(val) : utility::LittleFloat(val); + return m_endian == Endian::Big ? utility::BigFloat(val) : utility::LittleFloat(val); } template float readVal(std::enable_if_t>* = nullptr) { @@ -446,7 +446,7 @@ public: double readDouble() { double val = 0.0; readUBytesToBuf(&val, 8); - return m_endian == Big ? utility::BigDouble(val) : utility::LittleDouble(val); + return m_endian == Endian::Big ? utility::BigDouble(val) : utility::LittleDouble(val); } template double readVal(std::enable_if_t>* = nullptr) { @@ -513,7 +513,7 @@ public: atVec2f readVec2f() { simd_floats val = {}; readUBytesToBuf(val.data(), 8); - if (m_endian == Big) { + if (m_endian == Endian::Big) { val[0] = utility::BigFloat(val[0]); val[1] = utility::BigFloat(val[1]); } else { @@ -581,7 +581,7 @@ public: atVec3f readVec3f() { simd_floats val = {}; readUBytesToBuf(val.data(), 12); - if (m_endian == Big) { + if (m_endian == Endian::Big) { val[0] = utility::BigFloat(val[0]); val[1] = utility::BigFloat(val[1]); val[2] = utility::BigFloat(val[2]); @@ -650,7 +650,7 @@ public: atVec4f readVec4f() { simd_floats val = {}; readUBytesToBuf(val.data(), 16); - if (m_endian == Big) { + if (m_endian == Endian::Big) { val[0] = utility::BigFloat(val[0]); val[1] = utility::BigFloat(val[1]); val[2] = utility::BigFloat(val[2]); @@ -720,7 +720,7 @@ public: atVec2d readVec2d() { simd_doubles val = {}; readUBytesToBuf(val.data(), 16); - if (m_endian == Big) { + if (m_endian == Endian::Big) { val[0] = utility::BigDouble(val[0]); val[1] = utility::BigDouble(val[1]); } else { @@ -788,7 +788,7 @@ public: atVec3d readVec3d() { simd_doubles val = {}; readUBytesToBuf(val.data(), 24); - if (m_endian == Big) { + if (m_endian == Endian::Big) { val[0] = utility::BigDouble(val[0]); val[1] = utility::BigDouble(val[1]); val[2] = utility::BigDouble(val[2]); @@ -857,7 +857,7 @@ public: atVec4d readVec4d() { simd_doubles val = {}; readUBytesToBuf(val.data(), 32); - if (m_endian == Big) { + if (m_endian == Endian::Big) { val[0] = utility::BigDouble(val[0]); val[1] = utility::BigDouble(val[1]); val[2] = utility::BigDouble(val[2]); diff --git a/include/athena/IStreamWriter.hpp b/include/athena/IStreamWriter.hpp index 629d86c..923e42f 100644 --- a/include/athena/IStreamWriter.hpp +++ b/include/athena/IStreamWriter.hpp @@ -91,10 +91,11 @@ public: * @param val The value to write to the buffer */ void writeInt16(atInt16 val) { - if (m_endian == Big) + if (m_endian == Endian::Big) { utility::BigInt16(val); - else + } else { utility::LittleInt16(val); + } writeUBytes((atUint8*)&val, 2); } void writeVal(atInt16 val) { writeInt16(val); } @@ -151,10 +152,11 @@ public: * @param val The value to write to the buffer */ void writeInt32(atInt32 val) { - if (m_endian == Big) + if (m_endian == Endian::Big) { utility::BigInt32(val); - else + } else { utility::LittleInt32(val); + } writeUBytes((atUint8*)&val, 4); } void writeVal(atInt32 val) { writeInt32(val); } @@ -211,10 +213,11 @@ public: * @param val The value to write to the buffer */ void writeInt64(atInt64 val) { - if (m_endian == Big) + if (m_endian == Endian::Big) { utility::BigInt64(val); - else + } else { utility::LittleInt64(val); + } writeUBytes((atUint8*)&val, 8); } void writeVal(atInt64 val) { writeInt64(val); } @@ -271,10 +274,11 @@ public: * @param val The value to write to the buffer */ void writeFloat(float val) { - if (m_endian == Big) + if (m_endian == Endian::Big) { val = utility::BigFloat(val); - else + } else { val = utility::LittleFloat(val); + } writeUBytes((atUint8*)&val, 4); } void writeVal(float val) { writeFloat(val); } @@ -307,10 +311,11 @@ public: * @param val The value to write to the buffer */ void writeDouble(double val) { - if (m_endian == Big) + if (m_endian == Endian::Big) { utility::BigDouble(val); - else + } else { utility::LittleDouble(val); + } writeUBytes((atUint8*)&val, 8); } void writeVal(double val) { writeDouble(val); } @@ -354,7 +359,7 @@ public: */ void writeVec2f(const atVec2f& vec) { simd_floats tmp(vec.simd); - if (m_endian == Big) { + if (m_endian == Endian::Big) { tmp[0] = utility::BigFloat(tmp[0]); tmp[1] = utility::BigFloat(tmp[1]); } else { @@ -398,7 +403,7 @@ public: */ void writeVec3f(const atVec3f& vec) { simd_floats tmp(vec.simd); - if (m_endian == Big) { + if (m_endian == Endian::Big) { tmp[0] = utility::BigFloat(tmp[0]); tmp[1] = utility::BigFloat(tmp[1]); tmp[2] = utility::BigFloat(tmp[2]); @@ -446,7 +451,7 @@ public: */ void writeVec4f(const atVec4f& vec) { simd_floats tmp(vec.simd); - if (m_endian == Big) { + if (m_endian == Endian::Big) { tmp[0] = utility::BigFloat(tmp[0]); tmp[1] = utility::BigFloat(tmp[1]); tmp[2] = utility::BigFloat(tmp[2]); @@ -498,7 +503,7 @@ public: */ void writeVec2d(const atVec2d& vec) { simd_doubles tmp(vec.simd); - if (m_endian == Big) { + if (m_endian == Endian::Big) { tmp[0] = utility::BigDouble(tmp[0]); tmp[1] = utility::BigDouble(tmp[1]); } else { @@ -542,7 +547,7 @@ public: */ void writeVec3d(const atVec3d& vec) { simd_doubles tmp(vec.simd); - if (m_endian == Big) { + if (m_endian == Endian::Big) { tmp[0] = utility::BigDouble(tmp[0]); tmp[1] = utility::BigDouble(tmp[1]); tmp[2] = utility::BigDouble(tmp[2]); @@ -590,7 +595,7 @@ public: */ void writeVec4d(const atVec4d& vec) { simd_doubles tmp(vec.simd); - if (m_endian == Big) { + if (m_endian == Endian::Big) { tmp[0] = utility::BigDouble(tmp[0]); tmp[1] = utility::BigDouble(tmp[1]); tmp[2] = utility::BigDouble(tmp[2]); From a9039e04e64e913b1cee1df271739d8234c9bd3a Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Fri, 27 Sep 2019 20:37:48 -0700 Subject: [PATCH 21/21] Fix AT_SPECIALIZE_* endian references --- include/athena/DNAOp.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/athena/DNAOp.hpp b/include/athena/DNAOp.hpp index bb10f83..f043038 100644 --- a/include/athena/DNAOp.hpp +++ b/include/athena/DNAOp.hpp @@ -1148,29 +1148,29 @@ void __BinarySizeProp64(const T& obj, size_t& s) { #define AT_SUBSPECIALIZE_DNA(...) \ template <> \ template <> \ - void __VA_ARGS__::Enumerate::BinarySize>(typename BinarySize::StreamT & s) { \ + void __VA_ARGS__::Enumerate::BinarySize>(typename BinarySize::StreamT & s) { \ _binarySize(s); \ } \ template <> \ template <> \ - void __VA_ARGS__::Enumerate::Read>(typename Read::StreamT & r) { \ + void __VA_ARGS__::Enumerate::Read>(typename Read::StreamT & r) { \ _read(r); \ } \ template <> \ template <> \ - void __VA_ARGS__::Enumerate::Write>(typename Write::StreamT & w) { \ + void __VA_ARGS__::Enumerate::Write>(typename Write::StreamT & w) { \ _write(w); \ } #define AT_SUBSPECIALIZE_DNA_YAML(...) \ template <> \ template <> \ - void __VA_ARGS__::Enumerate::ReadYaml>(typename ReadYaml::StreamT & r) { \ + void __VA_ARGS__::Enumerate::ReadYaml>(typename ReadYaml::StreamT & r) { \ _read(r); \ } \ template <> \ template <> \ - void __VA_ARGS__::Enumerate::WriteYaml>(typename WriteYaml::StreamT & w) { \ + void __VA_ARGS__::Enumerate::WriteYaml>(typename WriteYaml::StreamT & w) { \ _write(w); \ } \ AT_SUBSPECIALIZE_DNA(__VA_ARGS__)