From 7243c687a82eef87a4df604eae6725fae2570573 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 7 Dec 2018 19:18:17 -1000 Subject: [PATCH] New code style refactor --- Example/main.cpp | 53 +- atdna/main.cpp | 2510 +++++++++---------- atdna/test.cpp | 35 +- atdna/test.hpp | 112 +- include/LZ77/LZBase.hpp | 54 +- include/LZ77/LZLookupTable.hpp | 41 +- include/LZ77/LZType10.hpp | 11 +- include/LZ77/LZType11.hpp | 13 +- include/aes.hpp | 17 +- include/athena/ALTTPEnums.hpp | 128 +- include/athena/ALTTPFile.hpp | 96 +- include/athena/ALTTPFileReader.hpp | 52 +- include/athena/ALTTPFileWriter.hpp | 54 +- include/athena/ALTTPQuest.hpp | 1299 +++++----- include/athena/ALTTPStructs.hpp | 310 ++- include/athena/Checksums.hpp | 8 +- include/athena/ChecksumsLiterals.hpp | 305 +-- include/athena/Compression.hpp | 5 +- include/athena/DNA.hpp | 166 +- include/athena/DNAOp.hpp | 1749 ++++++------- include/athena/DNAYaml.hpp | 158 +- include/athena/Dir.hpp | 36 +- include/athena/FileInfo.hpp | 63 +- include/athena/FileReader.hpp | 81 +- include/athena/FileWriter.hpp | 135 +- include/athena/Global.hpp | 202 +- include/athena/IStream.hpp | 37 +- include/athena/IStreamReader.hpp | 2366 +++++++++-------- include/athena/IStreamWriter.hpp | 2098 ++++++++-------- include/athena/MCFile.hpp | 26 +- include/athena/MCFileReader.hpp | 52 +- include/athena/MCFileWriter.hpp | 57 +- include/athena/MCSlot.hpp | 11 +- include/athena/MemoryReader.hpp | 160 +- include/athena/MemoryWriter.hpp | 222 +- include/athena/PHYSFSFileReader.hpp | 69 +- include/athena/SakuraGlobal.hpp | 25 +- include/athena/SkywardSwordFile.hpp | 46 +- include/athena/SkywardSwordFileReader.hpp | 20 +- include/athena/SkywardSwordFileWriter.hpp | 19 +- include/athena/SkywardSwordQuest.hpp | 69 +- include/athena/Socket.hpp | 104 +- include/athena/Sprite.hpp | 94 +- include/athena/SpriteFile.hpp | 276 +- include/athena/SpriteFileReader.hpp | 26 +- include/athena/SpriteFileWriter.hpp | 24 +- include/athena/SpriteFrame.hpp | 56 +- include/athena/SpritePart.hpp | 174 +- include/athena/Types.hpp | 27 +- include/athena/Utility.hpp | 231 +- include/athena/VectorWriter.hpp | 67 +- include/athena/WiiBanner.hpp | 269 +- include/athena/WiiFile.hpp | 350 ++- include/athena/WiiImage.hpp | 107 +- include/athena/WiiSave.hpp | 99 +- include/athena/WiiSaveReader.hpp | 56 +- include/athena/WiiSaveWriter.hpp | 56 +- include/athena/YAMLCommon.hpp | 180 +- include/athena/YAMLDocReader.hpp | 280 +-- include/athena/YAMLDocWriter.hpp | 216 +- include/athena/ZQuestFile.hpp | 233 +- include/athena/ZQuestFileReader.hpp | 45 +- include/athena/ZQuestFileWriter.hpp | 47 +- include/athena/simd/parallelism_v2_simd.hpp | 424 ++-- include/athena/simd/simd.hpp | 27 +- include/athena/simd/simd_avx.hpp | 65 +- include/athena/simd/simd_sse.hpp | 119 +- include/bn.hpp | 6 +- include/ec.hpp | 7 +- include/optional.hpp | 984 ++++---- src/LZ77/LZBase.cpp | 179 +- src/LZ77/LZLookupTable.cpp | 215 +- src/LZ77/LZType10.cpp | 201 +- src/LZ77/LZType11.cpp | 364 ++- src/aes.cpp | 941 ++++--- src/athena/ALTTPFile.cpp | 55 +- src/athena/ALTTPFileReader.cpp | 406 ++- src/athena/ALTTPFileWriter.cpp | 377 ++- src/athena/ALTTPQuest.cpp | 1062 +++----- src/athena/Checksums.cpp | 362 ++- src/athena/Compression.cpp | 504 ++-- src/athena/DNAYaml.cpp | 2107 +++++++--------- src/athena/Dir.cpp | 115 +- src/athena/FileInfo.cpp | 247 +- src/athena/FileReader.cpp | 311 ++- src/athena/FileReaderWin32.cpp | 351 ++- src/athena/FileWriterGeneric.cpp | 47 +- src/athena/FileWriterNix.cpp | 183 +- src/athena/FileWriterWin32.cpp | 188 +- src/athena/Global.cpp | 111 +- src/athena/MCFile.cpp | 53 +- src/athena/MCFileReader.cpp | 42 +- src/athena/MCFileWriter.cpp | 54 +- src/athena/MCSlot.cpp | 9 +- src/athena/MemoryReader.cpp | 302 +-- src/athena/MemoryWriter.cpp | 504 ++-- src/athena/PHYSFSFileReader.cpp | 260 +- src/athena/SkywardSwordFile.cpp | 71 +- src/athena/SkywardSwordFileReader.cpp | 84 +- src/athena/SkywardSwordFileWriter.cpp | 90 +- src/athena/SkywardSwordQuest.cpp | 345 ++- src/athena/Socket.cpp | 429 ++-- src/athena/Sprite.cpp | 320 +-- src/athena/SpriteFile.cpp | 297 +-- src/athena/SpriteFileReader.cpp | 314 ++- src/athena/SpriteFileWriter.cpp | 129 +- src/athena/SpriteFrame.cpp | 65 +- src/athena/SpritePart.cpp | 111 +- src/athena/Utility.cpp | 328 ++- src/athena/VectorWriter.cpp | 139 +- src/athena/WiiBanner.cpp | 167 +- src/athena/WiiFile.cpp | 405 ++- src/athena/WiiImage.cpp | 108 +- src/athena/WiiSave.cpp | 85 +- src/athena/WiiSaveReader.cpp | 543 ++-- src/athena/WiiSaveWriter.cpp | 393 ++- src/athena/ZQuestFile.cpp | 145 +- src/athena/ZQuestFileReader.cpp | 173 +- src/athena/ZQuestFileWriter.cpp | 109 +- src/bn.cpp | 144 +- src/ec.cpp | 460 ++-- src/md5.cpp | 513 ++-- src/sha1.cpp | 388 ++- 123 files changed, 15125 insertions(+), 18399 deletions(-) diff --git a/Example/main.cpp b/Example/main.cpp index 5314176..a6f50f8 100644 --- a/Example/main.cpp +++ b/Example/main.cpp @@ -5,54 +5,51 @@ #include #endif -static void *xfb = nullptr; +static void* xfb = nullptr; static GXRModeObj* rmode = nullptr; #endif #include -int main() -{ +int main() { #if GEKKO - VIDEO_Init(); + VIDEO_Init(); #if HW_RVL - WPAD_Init(); + WPAD_Init(); #endif - PAD_Init(); + PAD_Init(); - rmode = VIDEO_GetPreferredMode(nullptr); - xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + rmode = VIDEO_GetPreferredMode(nullptr); + xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); - CON_Init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ); - CON_EnableGecko(CARD_SLOTB, true); + CON_Init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ); + CON_EnableGecko(CARD_SLOTB, true); - VIDEO_Configure(rmode); - VIDEO_SetBlack(false); + VIDEO_Configure(rmode); + VIDEO_SetBlack(false); - VIDEO_Flush(); + VIDEO_Flush(); + VIDEO_WaitVSync(); + if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync(); - if (rmode->viTVMode & VI_NON_INTERLACE) - VIDEO_WaitVSync(); - athena::io::MemoryCopyReader test("sd:/test.dat"); - while(true) - { + athena::io::MemoryCopyReader test("sd:/test.dat"); + while (true) { #if HW_RVL - WPAD_ScanPads(); + WPAD_ScanPads(); #endif - PAD_ScanPads(); - if (PAD_ButtonsDown(0) & PAD_BUTTON_START) - break; + PAD_ScanPads(); + if (PAD_ButtonsDown(0) & PAD_BUTTON_START) + break; #if HW_RVL - if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) - break; + if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) + break; #endif - VIDEO_WaitVSync(); - } + VIDEO_WaitVSync(); + } #endif - return 0; + return 0; } - diff --git a/atdna/main.cpp b/atdna/main.cpp index 032ff3d..adff63b 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -21,7 +21,7 @@ static unsigned AthenaError = 0; #define ATHENA_DNA_BASETYPE "struct athena::io::DNA" #ifndef INSTALL_PREFIX -#define INSTALL_PREFIX /usr/local +#define INSTALL_PREFIX / usr / local #endif #define XSTR(s) STR(s) #define STR(s) #s @@ -32,46 +32,33 @@ static llvm::cl::opt Verbose("v", llvm::cl::desc("verbose mode")); static llvm::cl::OptionCategory ATDNAFormatCategory("atdna options"); -static llvm::cl::opt OutputFilename("o", - llvm::cl::desc("Specify output filename"), - llvm::cl::value_desc("filename"), - llvm::cl::Prefix); +static llvm::cl::opt OutputFilename("o", llvm::cl::desc("Specify output filename"), + llvm::cl::value_desc("filename"), llvm::cl::Prefix); -static llvm::cl::opt FExceptions("fexceptions", - llvm::cl::desc("Enable C++ Exceptions")); -static llvm::cl::opt FMSCompat("fms-compatibility", - llvm::cl::desc("Enable MS header compatibility")); -static llvm::cl::opt FMSCompatVersion("fms-compatibility-version", - llvm::cl::desc("Specify MS compatibility version (18.00 for VS2013, 19.00 for VS2015)")); +static llvm::cl::opt FExceptions("fexceptions", llvm::cl::desc("Enable C++ Exceptions")); +static llvm::cl::opt FMSCompat("fms-compatibility", llvm::cl::desc("Enable MS header compatibility")); +static llvm::cl::opt + FMSCompatVersion("fms-compatibility-version", + llvm::cl::desc("Specify MS compatibility version (18.00 for VS2013, 19.00 for VS2015)")); -static llvm::cl::list InputFilenames(llvm::cl::Positional, - llvm::cl::desc(""), +static llvm::cl::list InputFilenames(llvm::cl::Positional, llvm::cl::desc(""), llvm::cl::ZeroOrMore); -static llvm::cl::list IncludeSearchPaths("I", - llvm::cl::desc("Header search path"), - llvm::cl::Prefix); +static llvm::cl::list IncludeSearchPaths("I", llvm::cl::desc("Header search path"), llvm::cl::Prefix); -static llvm::cl::list SystemIncludeSearchPaths("isystem", - llvm::cl::desc("System Header search path")); +static llvm::cl::list SystemIncludeSearchPaths("isystem", llvm::cl::desc("System Header search path")); -static llvm::cl::opt StandardCXXLib("stdlib", - llvm::cl::desc("Standard C++ library")); +static llvm::cl::opt StandardCXXLib("stdlib", llvm::cl::desc("Standard C++ library")); static llvm::cl::opt DepFile("MD", llvm::cl::desc("Make Dependency file")); -static llvm::cl::opt DepFileOut("MF", - llvm::cl::desc("Dependency file out path")); +static llvm::cl::opt DepFileOut("MF", llvm::cl::desc("Dependency file out path")); -static llvm::cl::list DepFileTargets("MT", - llvm::cl::desc("Dependency file targets")); +static llvm::cl::list DepFileTargets("MT", llvm::cl::desc("Dependency file targets")); -static llvm::cl::list SystemIncRoot("isysroot", - llvm::cl::desc("System include root")); +static llvm::cl::list SystemIncRoot("isysroot", llvm::cl::desc("System include root")); -static llvm::cl::list PreprocessorDefines("D", - llvm::cl::desc("Preprocessor define"), - llvm::cl::Prefix); +static llvm::cl::list PreprocessorDefines("D", llvm::cl::desc("Preprocessor define"), llvm::cl::Prefix); static llvm::cl::opt EmitIncludes("emit-includes", llvm::cl::desc("Emit DNA for included files (not just main file)")); @@ -83,1363 +70,1124 @@ using StreamOut = llvm::raw_pwrite_stream; using StreamOut = llvm::raw_fd_ostream; #endif -class ATDNAEmitVisitor : public clang::RecursiveASTVisitor -{ - clang::ASTContext& context; - StreamOut& fileOut; - - bool isDNARecord(const clang::CXXRecordDecl* record, std::string& baseDNA) - { - for (const clang::CXXBaseSpecifier& base : record->bases()) - { - const clang::QualType qtp = base.getType().getCanonicalType(); - if (!qtp.getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE)-1, ATHENA_DNA_BASETYPE)) - return true; - } - for (const clang::CXXBaseSpecifier& base : record->bases()) - { - clang::QualType qtp = base.getType().getCanonicalType(); - const clang::Type* tp = qtp.getTypePtrOrNull(); - if (tp) - { - const clang::CXXRecordDecl* rDecl = tp->getAsCXXRecordDecl(); - if (rDecl) - { - if (isDNARecord(rDecl, baseDNA)) - { - bool hasRead = false; - bool hasWrite = false; - for (const clang::CXXMethodDecl* method : rDecl->methods()) - { - std::string compName = method->getDeclName().getAsString(); - if (!compName.compare("read")) - hasRead = true; - else if (!compName.compare("write")) - hasWrite = true; - } - if (hasRead && hasWrite) - { - std::string templateStmt; - GetNestedTypeName(rDecl, templateStmt, baseDNA); - } - return true; - } - } - } - } - return false; - } - - int64_t GetSizeValue(const clang::Type* theType, unsigned width) - { - if (theType->isEnumeralType()) - { - clang::EnumType* eType = (clang::EnumType*)theType; - clang::EnumDecl* eDecl = eType->getDecl(); - theType = eDecl->getIntegerType().getCanonicalType().getTypePtr(); - - const clang::BuiltinType* bType = (clang::BuiltinType*)theType; - if (bType->isBooleanType()) - { - return 1; - } - else if (bType->isUnsignedInteger() || bType->isSignedInteger()) - { - return width / 8; - } - } - else if (theType->isBuiltinType()) - { - const clang::BuiltinType* bType = (clang::BuiltinType*)theType; - if (bType->isBooleanType()) - { - return 1; - } - else if (bType->isUnsignedInteger() || bType->isSignedInteger() || bType->isFloatingPoint()) - { - return width / 8; - } - } - else if (theType->isRecordType()) - { - const clang::CXXRecordDecl* rDecl = theType->getAsCXXRecordDecl(); - for (const clang::FieldDecl* field : rDecl->fields()) - { - if (!field->getName().compare("clangVec")) - { - const clang::VectorType* vType = (clang::VectorType*)field->getType().getTypePtr(); - if (vType->isVectorType()) - { - const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); - const uint64_t width = context.getTypeInfo(eType).Width; - if (!eType->isBuiltinType() || !eType->isFloatingPoint() || - (width != 32 && width != 64)) - continue; - if (vType->getNumElements() == 2) - { - return width / 8 * 2; - } - else if (vType->getNumElements() == 3) - { - return width / 8 * 3; - } - else if (vType->getNumElements() == 4) - { - return width / 8 * 4; - } - } - } - } - } - return 0; - } - - static std::string GetFieldString(const std::string& fieldName) - { - size_t underscorePos = fieldName.find('_'); - std::string idString = fieldName; - if (underscorePos != std::string::npos && underscorePos != fieldName.size() - 1) - idString.assign(fieldName.begin() + underscorePos + 1, fieldName.end()); - return idString; - } - - static std::string GetPropIdExpr(const clang::FieldDecl* field, const std::string& fieldName) - { - std::string fieldStr = GetFieldString(fieldName); - std::string propIdExpr = "\"" + fieldStr + "\""; - for (clang::Attr* attr : field->attrs()) - { - if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) - { - llvm::StringRef textRef = annot->getAnnotation(); - if (textRef.startswith_lower("rcrc32=")) - { - unsigned long num = strtoul(textRef.data() + 7, nullptr, 16); - std::string tmpS; - llvm::raw_string_ostream s(tmpS); - s << llvm::format("\"%s\", 0x%08X", fieldStr.c_str(), num); - propIdExpr = s.str(); - break; - } - } - } - return propIdExpr; - } - - static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& endianExpr) - { - - return "({" + propIdExpr + "}, " + fieldName + ", s)"; - } - - static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) - { - - return "({" + propIdExpr + "}, " + fieldName + ", s)"; - } - - static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr, const std::string& endianExpr) - { - return "({" + propIdExpr + "}, " + fieldName + ", " + sizeExpr + ", s)"; - } - - static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, const std::string& sizeExpr) - { - return "({" + propIdExpr + "}, " + fieldName + ", " + sizeExpr + ", s)"; - } - - static void RecurseNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) - { - if (!decl) - return; - RecurseNestedTypeName(decl->getParent(), templateStmt, qualType); - if (const clang::CXXRecordDecl* rec = clang::dyn_cast_or_null(decl)) - { - if (!qualType.empty()) - qualType += "::"; - qualType += rec->getName(); - if (const clang::ClassTemplateDecl* ct = rec->getDescribedClassTemplate()) - { - templateStmt += "template <"; - qualType += '<'; - bool needsComma = false; - for (const clang::NamedDecl* parm : *ct->getTemplateParameters()) - { - if (const clang::TemplateTypeParmDecl* tpParm = - clang::dyn_cast_or_null(parm)) - { - if (needsComma) - { - templateStmt += ", "; - qualType += ", "; - } - templateStmt += "class "s + tpParm->getName().data(); - qualType += tpParm->getName(); - needsComma = true; - } - else if (const clang::NonTypeTemplateParmDecl* nonTypeParm = - clang::dyn_cast_or_null(parm)) - { - if (needsComma) - { - templateStmt += ", "; - qualType += ", "; - } - templateStmt += nonTypeParm->getType().getAsString() + ' ' + nonTypeParm->getName().data(); - qualType += nonTypeParm->getName(); - needsComma = true; - } - } - templateStmt += ">\n"; - qualType += '>'; - } - } - else if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null(decl)) - { - if (!qualType.empty()) - qualType += "::"; - qualType += namedDecl->getName(); - } - } - - static void GetNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) - { - templateStmt.clear(); - qualType.clear(); - RecurseNestedTypeName(decl, templateStmt, qualType); - } - - static void RecurseNestedTypeSpecializations(const clang::DeclContext* decl, - std::vector>& specializations) - { - if (!decl) - { - specializations.emplace_back(); - return; - } - - std::vector> parentSpecializations; - RecurseNestedTypeSpecializations(decl->getParent(), parentSpecializations); - bool foundSpecializations = false; - if (const clang::CXXRecordDecl* rec = clang::dyn_cast_or_null(decl)) - { - if (const clang::ClassTemplateDecl* ct = rec->getDescribedClassTemplate()) - { - int numParms = 0; - for (const clang::NamedDecl* parm : *ct->getTemplateParameters()) - if (clang::dyn_cast_or_null(parm) || - clang::dyn_cast_or_null(parm)) - ++numParms; - - for (clang::Attr* attr : rec->attrs()) - { - if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) - { - llvm::StringRef textRef = annot->getAnnotation(); - if (textRef.startswith_lower("specparms=")) - { - llvm::SmallVector specParms; - textRef.substr(10).split(specParms, ','); - 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); - bool needsComma = false; - for (auto it = specParms.begin() + i * numParms; - it != specParms.end() && it != specParms.begin() + (i + 1) * numParms; ++it) - { - StringRef trimmed = it->trim(); - if (needsComma) - specializations.back().first += ", "; - specializations.back().first += trimmed; - needsComma = true; - } - specializations.back().first += ">"; - } - } - foundSpecializations = true; - break; - } - } - } - } - } - - 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 - specializations.push_back(parent); - } - } - - static std::vector> - GetNestedTypeSpecializations(const clang::DeclContext* decl) - { - std::vector> ret; - RecurseNestedTypeSpecializations(decl, ret); - return ret; - } - - void emitEnumerateFunc(clang::CXXRecordDecl* decl, const std::string& baseDNA) - { - std::string templateStmt; - std::string qualTypeStr; - GetNestedTypeName(decl, templateStmt, qualTypeStr); - - fileOut << templateStmt; - fileOut << "template \nvoid " << - qualTypeStr << "::Enumerate(typename Op::StreamT& s)\n{\n"; - - if (baseDNA.size()) - fileOut << " " << baseDNA << "::Enumerate(s);\n"; - - enum class NodeType - { - Do, - DoSeek, - DoAlign - }; - struct OutputNode - { - NodeType m_type = NodeType::Do; - 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) {} - }; - std::vector outputNodes; - - for (const clang::FieldDecl* field : decl->fields()) - { - clang::QualType qualType = field->getType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (!regType || regType->getTypeClass() == clang::Type::TemplateTypeParm) - continue; - while (regType->getTypeClass() == clang::Type::Elaborated || - regType->getTypeClass() == clang::Type::Typedef) - regType = regType->getUnqualifiedDesugaredType(); - - /* Resolve constant array */ - while (regType->getTypeClass() == clang::Type::ConstantArray) - { - const clang::ConstantArrayType* caType = (clang::ConstantArrayType*)regType; - qualType = caType->getElementType(); - regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Elaborated) - regType = regType->getUnqualifiedDesugaredType(); - } - - std::string fieldName = field->getName(); - std::string propIdExpr = GetPropIdExpr(field, fieldName); - - if (regType->getTypeClass() == clang::Type::TemplateSpecialization) - { - const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; - const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); - const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); - - if (!tsDecl->getName().compare("Value")) - { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) - { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr(); - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - - std::string ioOp; - bool isDNAType = false; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Type) - { - if (defaultEndian) - ioOp = GetOpString(fieldName, propIdExpr); - else - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - } - - if (ioOp.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); - } - else if (!tsDecl->getName().compare("Vector")) - { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 3) - { - const clang::NamedDecl* endianParm = classParms->getParam(2); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExpr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 1) - { - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - - if (argExpr->getStmtClass() == clang::Stmt::DeclRefExprClass) - { - clang::DeclRefExpr* drExpr = (clang::DeclRefExpr*)argExpr; - std::string testName = drExpr->getFoundDecl()->getNameAsString(); - for (auto i=outputNodes.rbegin() ; i != outputNodes.rend() ; ++i) - { - if (i->m_fieldName == testName) - { - i->m_squelched = true; - break; - } - } - } - llvm::raw_string_ostream strStream2(sizeExpr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } - } - else if (idx == 2) - { - defaultEndian = false; - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - ++idx; - } - - 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) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); - else - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); - } - } - - if (ioOp.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - if (sizeExpr.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use count variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); - } - else if (!tsDecl->getName().compare("Buffer")) - { - const clang::Expr* sizeExpr = nullptr; - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)arg.getAsExpr()->IgnoreImpCasts(); - if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - sizeExpr = argExpr; - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - } - if (sizeExprStr.empty()) - { - if (sizeExpr) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(sizeExpr->getLocStart(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(sizeExpr->getSourceRange(), true)); - } - else - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - } - continue; - } - - std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); - } - else if (!tsDecl->getName().compare("String")) - { - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - llvm::APSInt sizeLiteral; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - else if (expr->isIntegerConstantExpr(sizeLiteral, context)) - { - sizeExprStr = sizeLiteral.toString(10); - } - } - } - - std::string ioOp; - if (!sizeExprStr.empty()) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else - ioOp = GetOpString(fieldName, propIdExpr); - - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); - } - else if (!tsDecl->getName().compare("WString")) - { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) - { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExprStr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 0) - { - llvm::APSInt sizeLiteral; - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream2(sizeExprStr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } - else if (expr->isIntegerConstantExpr(sizeLiteral, context)) - { - sizeExprStr = sizeLiteral.toString(10); - } - } - else if (idx == 1) - { - defaultEndian = false; - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - ++idx; - } - - std::string ioOp; - if (!sizeExprStr.empty()) - { - if (defaultEndian) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); - } - else - { - if (defaultEndian) - ioOp = GetOpString(fieldName, propIdExpr); - else - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - - outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); - } - else if (!tsDecl->getName().compare("Seek")) - { - size_t idx = 0; - std::string offsetExprStr; - llvm::APSInt direction(64, 0); - const clang::Expr* directionExpr = nullptr; - bool bad = false; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (!idx) - { - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - llvm::APSInt offsetLiteral; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream(offsetExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - else if (expr->isIntegerConstantExpr(offsetLiteral, context)) - { - offsetExprStr = offsetLiteral.toString(10); - } - } - else - { - directionExpr = expr; - if (!expr->isIntegerConstantExpr(direction, context)) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); - diag.AddString("Unable to use non-constant direction expression in Athena"); - diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); - bad = true; - break; - } - } - } - ++idx; - } - if (bad) - continue; - - int64_t directionVal = direction.getSExtValue(); - if (directionVal < 0 || directionVal > 2) - { - if (directionExpr) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(directionExpr->getLocStart(), AthenaError); - diag.AddString("Direction parameter must be 'Begin', 'Current', or 'End'"); - diag.AddSourceRange(clang::CharSourceRange(directionExpr->getSourceRange(), true)); - } - else - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Direction parameter must be 'Begin', 'Current', or 'End'"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - } - 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); - } - else if (!tsDecl->getName().compare("Align")) - { - llvm::APSInt align(64, 0); - bool bad = false; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr(); - if (!expr->isIntegerConstantExpr(align, context)) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); - diag.AddString("Unable to use non-constant align expression in Athena"); - diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); - bad = true; - break; - } - } - } - if (bad) - continue; - - int64_t alignVal = align.getSExtValue(); - if (alignVal) - { - outputNodes.emplace_back(NodeType::DoAlign, fieldName, "("s + align.toString(10, true) + ", s)", false); - } - } - 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)) - outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); - } - } - } - - else if (regType->getTypeClass() == clang::Type::Record) - { - const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - std::string baseDNA; - if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) - outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); - } - } - - for (const OutputNode& node : outputNodes) - { - switch (node.m_type) - { - case NodeType::Do: - if (node.m_squelched) - fileOut << " DoSize" << node.m_ioOp << ";\n"; - else - fileOut << " Do" << node.m_ioOp << ";\n"; - break; - case NodeType::DoSeek: - fileOut << " DoSeek" << node.m_ioOp << ";\n"; - break; - case NodeType::DoAlign: - fileOut << " DoAlign" << node.m_ioOp << ";\n"; - break; - } - } - - fileOut << "}\n\n"; - } - - void emitLookupFunc(clang::CXXRecordDecl* decl, const std::string& baseDNA) - { - std::string templateStmt; - std::string qualTypeStr; - GetNestedTypeName(decl, templateStmt, qualTypeStr); - - fileOut << templateStmt; - fileOut << "template \nbool " << - qualTypeStr << "::Lookup(uint64_t hash, typename Op::StreamT& s)\n{\n"; - - if (baseDNA.size()) - fileOut << " if (" << baseDNA << "::Lookup(hash, s))\n" - << " return true;\n"; - - fileOut << " switch (hash)\n" - << " {\n"; - - for (const clang::FieldDecl* field : decl->fields()) - { - clang::QualType qualType = field->getType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (!regType || regType->getTypeClass() == clang::Type::TemplateTypeParm) - continue; - while (regType->getTypeClass() == clang::Type::Elaborated || - regType->getTypeClass() == clang::Type::Typedef) - regType = regType->getUnqualifiedDesugaredType(); - - /* Resolve constant array */ - while (regType->getTypeClass() == clang::Type::ConstantArray) - { - const clang::ConstantArrayType* caType = (clang::ConstantArrayType*)regType; - qualType = caType->getElementType(); - regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Elaborated) - regType = regType->getUnqualifiedDesugaredType(); - } - - std::string fieldName = field->getName(); - std::string propIdExpr = GetPropIdExpr(field, fieldName); - - if (regType->getTypeClass() == clang::Type::TemplateSpecialization) - { - const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; - const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); - const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); - - if (!tsDecl->getName().compare("Value")) - { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) - { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr(); - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - - std::string ioOp; - bool isDNAType = false; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Type) - { - if (defaultEndian) - ioOp = GetOpString(fieldName, propIdExpr); - else - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - } - - if (ioOp.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - - } - else if (!tsDecl->getName().compare("Vector")) - { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 3) - { - const clang::NamedDecl* endianParm = classParms->getParam(2); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExpr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 1) - { - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream2(sizeExpr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } - } - else if (idx == 2) - { - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - ++idx; - } - - 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) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); - else - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); - } - } - - if (ioOp.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - if (sizeExpr.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use count variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } - else if (!tsDecl->getName().compare("Buffer")) - { - const clang::Expr* sizeExpr = nullptr; - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)arg.getAsExpr()->IgnoreImpCasts(); - if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - sizeExpr = argExpr; - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - } - if (sizeExprStr.empty()) - { - if (sizeExpr) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(sizeExpr->getLocStart(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(sizeExpr->getSourceRange(), true)); - } - else - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - } - continue; - } - - std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } - else if (!tsDecl->getName().compare("String")) - { - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - llvm::APSInt sizeLiteral; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - else if (expr->isIntegerConstantExpr(sizeLiteral, context)) - { - sizeExprStr = sizeLiteral.toString(10); - } - } - } - - std::string ioOp; - if (!sizeExprStr.empty()) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else - ioOp = GetOpString(fieldName, propIdExpr); - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } - else if (!tsDecl->getName().compare("WString")) - { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) - { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExprStr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 0) - { - llvm::APSInt sizeLiteral; - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) - { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream2(sizeExprStr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } - else if (expr->isIntegerConstantExpr(sizeLiteral, context)) - { - sizeExprStr = sizeLiteral.toString(10); - } - } - else if (idx == 1) - { - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - ++idx; - } - - std::string ioOp; - if (!sizeExprStr.empty()) - { - if (defaultEndian) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); - } - else - { - if (defaultEndian) - ioOp = GetOpString(fieldName, propIdExpr); - else - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } - 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)) - { - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" - << " return true;\n"; - } - } - } - } - - else if (regType->getTypeClass() == clang::Type::Record) - { - const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - std::string baseDNA; - if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) - { - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" - << " return true;\n"; - } - } - } - - fileOut << " default:\n return false;\n }\n}\n\n"; - } - -public: - explicit ATDNAEmitVisitor(clang::ASTContext& ctxin, StreamOut& fo) - : context(ctxin), fileOut(fo) {} - - bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) - { - if (!EmitIncludes && !context.getSourceManager().isInMainFile(decl->getLocation())) - return true; - - if (decl->isInvalidDecl() || !decl->hasDefinition() || !decl->isCompleteDefinition()) - return true; - - if (!decl->getNumBases()) - return true; - - /* First ensure this inherits from struct athena::io::DNA */ - std::string baseDNA; - if (!isDNARecord(decl, baseDNA)) - return true; - - /* Determine if is is a YAML DNA */ - bool isYamlDNA = false; - for (const clang::CXXMethodDecl* method : decl->methods()) - if (method->getDeclName().isIdentifier() && - (!method->getName().compare(llvm::StringLiteral("read")) || - !method->getName().compare(llvm::StringLiteral("write"))) && method->getNumParams() == 1 && - method->getParamDecl(0)->getType().getAsString() == "athena::io::YAMLDocReader &") - { - isYamlDNA = true; - break; - } - - /* Determine if this is a regular DNA or PropDNA */ - bool isPropDNA = false; - for (const clang::Decl* d : decl->decls()) - if (const clang::FunctionTemplateDecl* m = clang::dyn_cast_or_null(d)) - if (m->getDeclName().isIdentifier() && !m->getName().compare(llvm::StringLiteral("Lookup"))) - { - isPropDNA = true; - break; - } - - /* Make sure there isn't Delete meta type */ - for (const clang::FieldDecl* field : decl->fields()) - { - clang::QualType qualType = field->getType().getCanonicalType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (regType) - { - const clang::CXXRecordDecl* rDecl = regType->getAsCXXRecordDecl(); - if (rDecl) - { - if (!rDecl->getName().compare("Delete")) - { - const clang::CXXRecordDecl* rParentDecl = llvm::dyn_cast_or_null(rDecl->getParent()); - if (rParentDecl) - { - std::string parentCheck = rParentDecl->getTypeForDecl()->getCanonicalTypeInternal().getAsString(); - if (!parentCheck.compare(0, sizeof(ATHENA_DNA_BASETYPE)-1, ATHENA_DNA_BASETYPE)) - return true; - } - } - } - } - } - - std::vector> specializations = GetNestedTypeSpecializations(decl); - - emitEnumerateFunc(decl, baseDNA); - if (isPropDNA) - { - emitLookupFunc(decl, baseDNA); - for (const auto& specialization : specializations) - fileOut << "AT_SPECIALIZE_PROPDNA(" << specialization.first << ")\n"; - } - else if (isYamlDNA) - { - for (const auto& specialization : specializations) - fileOut << "AT_SPECIALIZE_DNA_YAML(" << specialization.first << ")\n"; - } - else - { - for (const auto& specialization : specializations) - fileOut << "AT_SPECIALIZE_DNA(" << specialization.first << ")\n"; - } - fileOut << "\n\n"; - - for (const auto& specialization : specializations) - { - for (int i = 0; i < specialization.second; ++i) - fileOut << "template <>\n"; - fileOut << "const char* " << specialization.first << - "::DNAType()\n{\n return \"" << specialization.first << "\";\n}\n"; - } - fileOut << "\n\n"; - +class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { + clang::ASTContext& context; + StreamOut& fileOut; + + bool isDNARecord(const clang::CXXRecordDecl* record, std::string& baseDNA) { + for (const clang::CXXBaseSpecifier& base : record->bases()) { + const clang::QualType qtp = base.getType().getCanonicalType(); + if (!qtp.getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE) - 1, ATHENA_DNA_BASETYPE)) return true; } -}; - -class ATDNAConsumer : public clang::ASTConsumer -{ - std::unique_ptr fileOut; - StreamOut& fileOutOld; - ATDNAEmitVisitor emitVisitor; -public: - explicit ATDNAConsumer(clang::ASTContext& context, std::unique_ptr&& fo, StreamOut* foOld) - : fileOut(std::move(fo)), - fileOutOld(*foOld), - emitVisitor(context, *foOld) {} - - void HandleTranslationUnit(clang::ASTContext& context) override - { - /* Write file head */ - fileOutOld << "/* Auto generated atdna implementation */\n" - "#include \"athena/DNAOp.hpp\"\n"; - for (const std::string& inputf : InputFilenames) - fileOutOld << "#include \"" << inputf << "\"\n"; - fileOutOld << "\n"; - - /* Emit file */ - emitVisitor.TraverseDecl(context.getTranslationUnitDecl()); + for (const clang::CXXBaseSpecifier& base : record->bases()) { + clang::QualType qtp = base.getType().getCanonicalType(); + const clang::Type* tp = qtp.getTypePtrOrNull(); + if (tp) { + const clang::CXXRecordDecl* rDecl = tp->getAsCXXRecordDecl(); + if (rDecl) { + if (isDNARecord(rDecl, baseDNA)) { + bool hasRead = false; + bool hasWrite = false; + for (const clang::CXXMethodDecl* method : rDecl->methods()) { + std::string compName = method->getDeclName().getAsString(); + if (!compName.compare("read")) + hasRead = true; + else if (!compName.compare("write")) + hasWrite = true; + } + if (hasRead && hasWrite) { + std::string templateStmt; + GetNestedTypeName(rDecl, templateStmt, baseDNA); + } + return true; + } + } + } } -}; + return false; + } -class ATDNAAction : public clang::ASTFrontendAction -{ - /* Used by LLVM 3.9+; client owns stream */ - std::unique_ptr MakeStreamOut(std::unique_ptr&& so, StreamOut*& outPtr) - { - outPtr = so.get(); - return std::move(so); - } + int64_t GetSizeValue(const clang::Type* theType, unsigned width) { + if (theType->isEnumeralType()) { + clang::EnumType* eType = (clang::EnumType*)theType; + clang::EnumDecl* eDecl = eType->getDecl(); + theType = eDecl->getIntegerType().getCanonicalType().getTypePtr(); - /* Used by previous versions of LLVM; CompilerInstance owns stream */ - std::unique_ptr MakeStreamOut(StreamOut* so, StreamOut*& outPtr) - { - outPtr = so; - return {}; - } - - std::unique_ptr TheDependencyFileGenerator; - -public: - explicit ATDNAAction() = default; - std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, - llvm::StringRef /*filename*/) override - { - clang::DependencyOutputOptions DepOpts; - DepOpts.OutputFile = DepFileOut.getValue(); - DepOpts.Targets = DepFileTargets; - if (!DepOpts.OutputFile.empty()) - TheDependencyFileGenerator.reset( - clang::DependencyFileGenerator::CreateAndAttachToPreprocessor(compiler.getPreprocessor(), DepOpts)); - - std::unique_ptr fileout; - StreamOut* fileoutOld; - if (OutputFilename.size()) - fileout = MakeStreamOut(compiler.createOutputFile(OutputFilename, false, true, "", "", true), fileoutOld); - else - fileout = MakeStreamOut(compiler.createDefaultOutputFile(false, "a", "cpp"), fileoutOld); - AthenaError = compiler.getASTContext().getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Athena error: %0"); - return std::unique_ptr(new ATDNAConsumer(compiler.getASTContext(), std::move(fileout), fileoutOld)); - } -}; - -int main(int argc, const char** argv) -{ - llvm::cl::ParseCommandLineOptions(argc, argv, "Athena DNA Generator"); - if (Help) - llvm::cl::PrintHelpMessage(); - - std::vector args = {"clang-tool", -#ifdef __linux__ - "--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 fman(new clang::FileManager(clang::FileSystemOptions())); - ATDNAAction* action = new ATDNAAction(); - clang::tooling::ToolInvocation TI(args, action, fman.get()); - if (!TI.run()) + const clang::BuiltinType* bType = (clang::BuiltinType*)theType; + if (bType->isBooleanType()) { return 1; - + } else if (bType->isUnsignedInteger() || bType->isSignedInteger()) { + return width / 8; + } + } else if (theType->isBuiltinType()) { + const clang::BuiltinType* bType = (clang::BuiltinType*)theType; + if (bType->isBooleanType()) { + return 1; + } else if (bType->isUnsignedInteger() || bType->isSignedInteger() || bType->isFloatingPoint()) { + return width / 8; + } + } else if (theType->isRecordType()) { + const clang::CXXRecordDecl* rDecl = theType->getAsCXXRecordDecl(); + for (const clang::FieldDecl* field : rDecl->fields()) { + if (!field->getName().compare("clangVec")) { + const clang::VectorType* vType = (clang::VectorType*)field->getType().getTypePtr(); + if (vType->isVectorType()) { + const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + const uint64_t width = context.getTypeInfo(eType).Width; + if (!eType->isBuiltinType() || !eType->isFloatingPoint() || (width != 32 && width != 64)) + continue; + if (vType->getNumElements() == 2) { + return width / 8 * 2; + } else if (vType->getNumElements() == 3) { + return width / 8 * 3; + } else if (vType->getNumElements() == 4) { + return width / 8 * 4; + } + } + } + } + } return 0; + } + + static std::string GetFieldString(const std::string& fieldName) { + size_t underscorePos = fieldName.find('_'); + std::string idString = fieldName; + if (underscorePos != std::string::npos && underscorePos != fieldName.size() - 1) + idString.assign(fieldName.begin() + underscorePos + 1, fieldName.end()); + return idString; + } + + static std::string GetPropIdExpr(const clang::FieldDecl* field, const std::string& fieldName) { + std::string fieldStr = GetFieldString(fieldName); + std::string propIdExpr = "\"" + fieldStr + "\""; + for (clang::Attr* attr : field->attrs()) { + if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) { + llvm::StringRef textRef = annot->getAnnotation(); + if (textRef.startswith_lower("rcrc32=")) { + unsigned long num = strtoul(textRef.data() + 7, nullptr, 16); + std::string tmpS; + llvm::raw_string_ostream s(tmpS); + s << llvm::format("\"%s\", 0x%08X", fieldStr.c_str(), num); + propIdExpr = s.str(); + break; + } + } + } + return propIdExpr; + } + + static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr, + const std::string& endianExpr) { + + return "({" + propIdExpr + "}, " + fieldName + ", s)"; + } + + static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) { + + return "({" + propIdExpr + "}, " + fieldName + ", s)"; + } + + static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, + const std::string& sizeExpr, const std::string& endianExpr) { + return "({" + propIdExpr + "}, " + fieldName + ", " + sizeExpr + ", s)"; + } + + static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, + const std::string& sizeExpr) { + return "({" + propIdExpr + "}, " + fieldName + ", " + sizeExpr + ", s)"; + } + + static void RecurseNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) { + if (!decl) + return; + RecurseNestedTypeName(decl->getParent(), templateStmt, qualType); + if (const clang::CXXRecordDecl* rec = clang::dyn_cast_or_null(decl)) { + if (!qualType.empty()) + qualType += "::"; + qualType += rec->getName(); + if (const clang::ClassTemplateDecl* ct = rec->getDescribedClassTemplate()) { + templateStmt += "template <"; + qualType += '<'; + bool needsComma = false; + for (const clang::NamedDecl* parm : *ct->getTemplateParameters()) { + if (const clang::TemplateTypeParmDecl* tpParm = clang::dyn_cast_or_null(parm)) { + if (needsComma) { + templateStmt += ", "; + qualType += ", "; + } + templateStmt += "class "s + tpParm->getName().data(); + qualType += tpParm->getName(); + needsComma = true; + } else if (const clang::NonTypeTemplateParmDecl* nonTypeParm = + clang::dyn_cast_or_null(parm)) { + if (needsComma) { + templateStmt += ", "; + qualType += ", "; + } + templateStmt += nonTypeParm->getType().getAsString() + ' ' + nonTypeParm->getName().data(); + qualType += nonTypeParm->getName(); + needsComma = true; + } + } + templateStmt += ">\n"; + qualType += '>'; + } + } else if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null(decl)) { + if (!qualType.empty()) + qualType += "::"; + qualType += namedDecl->getName(); + } + } + + static void GetNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) { + templateStmt.clear(); + qualType.clear(); + RecurseNestedTypeName(decl, templateStmt, qualType); + } + + static void RecurseNestedTypeSpecializations(const clang::DeclContext* decl, + std::vector>& specializations) { + if (!decl) { + specializations.emplace_back(); + return; + } + + std::vector> parentSpecializations; + RecurseNestedTypeSpecializations(decl->getParent(), parentSpecializations); + bool foundSpecializations = false; + if (const clang::CXXRecordDecl* rec = clang::dyn_cast_or_null(decl)) { + if (const clang::ClassTemplateDecl* ct = rec->getDescribedClassTemplate()) { + int numParms = 0; + for (const clang::NamedDecl* parm : *ct->getTemplateParameters()) + if (clang::dyn_cast_or_null(parm) || + clang::dyn_cast_or_null(parm)) + ++numParms; + + for (clang::Attr* attr : rec->attrs()) { + if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) { + llvm::StringRef textRef = annot->getAnnotation(); + if (textRef.startswith_lower("specparms=")) { + llvm::SmallVector specParms; + textRef.substr(10).split(specParms, ','); + 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); + bool needsComma = false; + for (auto it = specParms.begin() + i * numParms; + it != specParms.end() && it != specParms.begin() + (i + 1) * numParms; ++it) { + StringRef trimmed = it->trim(); + if (needsComma) + specializations.back().first += ", "; + specializations.back().first += trimmed; + needsComma = true; + } + specializations.back().first += ">"; + } + } + foundSpecializations = true; + break; + } + } + } + } + } + + 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 + specializations.push_back(parent); + } + } + + static std::vector> GetNestedTypeSpecializations(const clang::DeclContext* decl) { + std::vector> ret; + RecurseNestedTypeSpecializations(decl, ret); + return ret; + } + + void emitEnumerateFunc(clang::CXXRecordDecl* decl, const std::string& baseDNA) { + std::string templateStmt; + std::string qualTypeStr; + GetNestedTypeName(decl, templateStmt, qualTypeStr); + + fileOut << templateStmt; + fileOut << "template \nvoid " << qualTypeStr << "::Enumerate(typename Op::StreamT& s)\n{\n"; + + if (baseDNA.size()) + fileOut << " " << baseDNA << "::Enumerate(s);\n"; + + enum class NodeType { Do, DoSeek, DoAlign }; + struct OutputNode { + NodeType m_type = NodeType::Do; + 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) {} + }; + std::vector outputNodes; + + for (const clang::FieldDecl* field : decl->fields()) { + clang::QualType qualType = field->getType(); + const clang::Type* regType = qualType.getTypePtrOrNull(); + if (!regType || regType->getTypeClass() == clang::Type::TemplateTypeParm) + continue; + while (regType->getTypeClass() == clang::Type::Elaborated || regType->getTypeClass() == clang::Type::Typedef) + regType = regType->getUnqualifiedDesugaredType(); + + /* Resolve constant array */ + while (regType->getTypeClass() == clang::Type::ConstantArray) { + const clang::ConstantArrayType* caType = (clang::ConstantArrayType*)regType; + qualType = caType->getElementType(); + regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::Elaborated) + regType = regType->getUnqualifiedDesugaredType(); + } + + std::string fieldName = field->getName(); + std::string propIdExpr = GetPropIdExpr(field, fieldName); + + if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { + const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; + const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); + const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); + + if (!tsDecl->getName().compare("Value")) { + llvm::APSInt endian(64, -1); + std::string endianExprStr; + bool defaultEndian = true; + if (classParms->size() >= 2) { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + llvm::raw_string_ostream strStream(endianExprStr); + nttParm->print(strStream, context.getPrintingPolicy()); + } + } + + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr(); + llvm::raw_string_ostream strStream(endianExprStr); + expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + defaultEndian = false; + } + } + + std::string ioOp; + bool isDNAType = false; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Type) { + if (defaultEndian) + ioOp = GetOpString(fieldName, propIdExpr); + else + ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); + } + } + + if (ioOp.empty()) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + } else if (!tsDecl->getName().compare("Vector")) { + llvm::APSInt endian(64, -1); + std::string endianExprStr; + bool defaultEndian = true; + if (classParms->size() >= 3) { + const clang::NamedDecl* endianParm = classParms->getParam(2); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + llvm::raw_string_ostream strStream(endianExprStr); + nttParm->print(strStream, context.getPrintingPolicy()); + } + } + + std::string sizeExpr; + size_t idx = 0; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + if (idx == 1) { + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + + if (argExpr->getStmtClass() == clang::Stmt::DeclRefExprClass) { + clang::DeclRefExpr* drExpr = (clang::DeclRefExpr*)argExpr; + std::string testName = drExpr->getFoundDecl()->getNameAsString(); + for (auto i = outputNodes.rbegin(); i != outputNodes.rend(); ++i) { + if (i->m_fieldName == testName) { + i->m_squelched = true; + break; + } + } + } + llvm::raw_string_ostream strStream2(sizeExpr); + argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); + } + } else if (idx == 2) { + defaultEndian = false; + llvm::raw_string_ostream strStream(endianExprStr); + expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + } + ++idx; + } + + 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) + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); + else + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); + } + } + + if (ioOp.empty()) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + if (sizeExpr.empty()) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use count variable with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + } else if (!tsDecl->getName().compare("Buffer")) { + const clang::Expr* sizeExpr = nullptr; + std::string sizeExprStr; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::UnaryExprOrTypeTraitExpr* uExpr = + (clang::UnaryExprOrTypeTraitExpr*)arg.getAsExpr()->IgnoreImpCasts(); + if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + sizeExpr = argExpr; + llvm::raw_string_ostream strStream(sizeExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + } + } + if (sizeExprStr.empty()) { + if (sizeExpr) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(sizeExpr->getLocStart(), AthenaError); + diag.AddString("Unable to use size variable with Athena"); + diag.AddSourceRange(clang::CharSourceRange(sizeExpr->getSourceRange(), true)); + } else { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use size variable with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + continue; + } + + std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); + + outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + } else if (!tsDecl->getName().compare("String")) { + std::string sizeExprStr; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + llvm::APSInt sizeLiteral; + if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + llvm::raw_string_ostream strStream(sizeExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } else if (expr->isIntegerConstantExpr(sizeLiteral, context)) { + sizeExprStr = sizeLiteral.toString(10); + } + } + } + + std::string ioOp; + if (!sizeExprStr.empty()) + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); + else + ioOp = GetOpString(fieldName, propIdExpr); + + outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + } else if (!tsDecl->getName().compare("WString")) { + llvm::APSInt endian(64, -1); + std::string endianExprStr; + bool defaultEndian = true; + if (classParms->size() >= 2) { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + llvm::raw_string_ostream strStream(endianExprStr); + nttParm->print(strStream, context.getPrintingPolicy()); + } + } + + std::string sizeExprStr; + size_t idx = 0; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + if (idx == 0) { + llvm::APSInt sizeLiteral; + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + llvm::raw_string_ostream strStream2(sizeExprStr); + argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); + } else if (expr->isIntegerConstantExpr(sizeLiteral, context)) { + sizeExprStr = sizeLiteral.toString(10); + } + } else if (idx == 1) { + defaultEndian = false; + llvm::raw_string_ostream strStream(endianExprStr); + expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + } + ++idx; + } + + std::string ioOp; + if (!sizeExprStr.empty()) { + if (defaultEndian) + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); + else + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); + } else { + if (defaultEndian) + ioOp = GetOpString(fieldName, propIdExpr); + else + ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); + } + + outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false); + } else if (!tsDecl->getName().compare("Seek")) { + size_t idx = 0; + std::string offsetExprStr; + llvm::APSInt direction(64, 0); + const clang::Expr* directionExpr = nullptr; + bool bad = false; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + if (!idx) { + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + llvm::APSInt offsetLiteral; + if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + llvm::raw_string_ostream strStream(offsetExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } else if (expr->isIntegerConstantExpr(offsetLiteral, context)) { + offsetExprStr = offsetLiteral.toString(10); + } + } else { + directionExpr = expr; + if (!expr->isIntegerConstantExpr(direction, context)) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); + diag.AddString("Unable to use non-constant direction expression in Athena"); + diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); + bad = true; + break; + } + } + } + ++idx; + } + if (bad) + continue; + + int64_t directionVal = direction.getSExtValue(); + if (directionVal < 0 || directionVal > 2) { + if (directionExpr) { + clang::DiagnosticBuilder diag = + context.getDiagnostics().Report(directionExpr->getLocStart(), AthenaError); + diag.AddString("Direction parameter must be 'Begin', 'Current', or 'End'"); + diag.AddSourceRange(clang::CharSourceRange(directionExpr->getSourceRange(), true)); + } else { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Direction parameter must be 'Begin', 'Current', or 'End'"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + 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); + } else if (!tsDecl->getName().compare("Align")) { + llvm::APSInt align(64, 0); + bool bad = false; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr(); + if (!expr->isIntegerConstantExpr(align, context)) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); + diag.AddString("Unable to use non-constant align expression in Athena"); + diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); + bad = true; + break; + } + } + } + if (bad) + continue; + + int64_t alignVal = align.getSExtValue(); + if (alignVal) { + outputNodes.emplace_back(NodeType::DoAlign, fieldName, "("s + align.toString(10, true) + ", s)", false); + } + } 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)) + outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); + } + } + } + + else if (regType->getTypeClass() == clang::Type::Record) { + const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); + std::string baseDNA; + if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) + outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false); + } + } + + for (const OutputNode& node : outputNodes) { + switch (node.m_type) { + case NodeType::Do: + if (node.m_squelched) + fileOut << " DoSize" << node.m_ioOp << ";\n"; + else + fileOut << " Do" << node.m_ioOp << ";\n"; + break; + case NodeType::DoSeek: + fileOut << " DoSeek" << node.m_ioOp << ";\n"; + break; + case NodeType::DoAlign: + fileOut << " DoAlign" << node.m_ioOp << ";\n"; + break; + } + } + + fileOut << "}\n\n"; + } + + void emitLookupFunc(clang::CXXRecordDecl* decl, const std::string& baseDNA) { + std::string templateStmt; + std::string qualTypeStr; + GetNestedTypeName(decl, templateStmt, qualTypeStr); + + fileOut << templateStmt; + fileOut << "template \nbool " << qualTypeStr << "::Lookup(uint64_t hash, typename Op::StreamT& s)\n{\n"; + + if (baseDNA.size()) + fileOut << " if (" << baseDNA << "::Lookup(hash, s))\n" + << " return true;\n"; + + fileOut << " switch (hash)\n" + << " {\n"; + + for (const clang::FieldDecl* field : decl->fields()) { + clang::QualType qualType = field->getType(); + const clang::Type* regType = qualType.getTypePtrOrNull(); + if (!regType || regType->getTypeClass() == clang::Type::TemplateTypeParm) + continue; + while (regType->getTypeClass() == clang::Type::Elaborated || regType->getTypeClass() == clang::Type::Typedef) + regType = regType->getUnqualifiedDesugaredType(); + + /* Resolve constant array */ + while (regType->getTypeClass() == clang::Type::ConstantArray) { + const clang::ConstantArrayType* caType = (clang::ConstantArrayType*)regType; + qualType = caType->getElementType(); + regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::Elaborated) + regType = regType->getUnqualifiedDesugaredType(); + } + + std::string fieldName = field->getName(); + std::string propIdExpr = GetPropIdExpr(field, fieldName); + + if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { + const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; + const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); + const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); + + if (!tsDecl->getName().compare("Value")) { + llvm::APSInt endian(64, -1); + std::string endianExprStr; + bool defaultEndian = true; + if (classParms->size() >= 2) { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + llvm::raw_string_ostream strStream(endianExprStr); + nttParm->print(strStream, context.getPrintingPolicy()); + } + } + + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr(); + llvm::raw_string_ostream strStream(endianExprStr); + expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + defaultEndian = false; + } + } + + std::string ioOp; + bool isDNAType = false; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Type) { + if (defaultEndian) + ioOp = GetOpString(fieldName, propIdExpr); + else + ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); + } + } + + if (ioOp.empty()) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << ioOp << ";\n" + << " return true;\n"; + + } else if (!tsDecl->getName().compare("Vector")) { + llvm::APSInt endian(64, -1); + std::string endianExprStr; + bool defaultEndian = true; + if (classParms->size() >= 3) { + const clang::NamedDecl* endianParm = classParms->getParam(2); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + llvm::raw_string_ostream strStream(endianExprStr); + nttParm->print(strStream, context.getPrintingPolicy()); + } + } + + std::string sizeExpr; + size_t idx = 0; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + if (idx == 1) { + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + llvm::raw_string_ostream strStream2(sizeExpr); + argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); + } + } else if (idx == 2) { + llvm::raw_string_ostream strStream(endianExprStr); + expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + defaultEndian = false; + } + } + ++idx; + } + + 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) + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); + else + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); + } + } + + if (ioOp.empty()) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + if (sizeExpr.empty()) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use count variable with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << ioOp << ";\n" + << " return true;\n"; + } else if (!tsDecl->getName().compare("Buffer")) { + const clang::Expr* sizeExpr = nullptr; + std::string sizeExprStr; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::UnaryExprOrTypeTraitExpr* uExpr = + (clang::UnaryExprOrTypeTraitExpr*)arg.getAsExpr()->IgnoreImpCasts(); + if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + sizeExpr = argExpr; + llvm::raw_string_ostream strStream(sizeExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + } + } + if (sizeExprStr.empty()) { + if (sizeExpr) { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(sizeExpr->getLocStart(), AthenaError); + diag.AddString("Unable to use size variable with Athena"); + diag.AddSourceRange(clang::CharSourceRange(sizeExpr->getSourceRange(), true)); + } else { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use size variable with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + continue; + } + + std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); + + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << ioOp << ";\n" + << " return true;\n"; + } else if (!tsDecl->getName().compare("String")) { + std::string sizeExprStr; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + llvm::APSInt sizeLiteral; + if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + llvm::raw_string_ostream strStream(sizeExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } else if (expr->isIntegerConstantExpr(sizeLiteral, context)) { + sizeExprStr = sizeLiteral.toString(10); + } + } + } + + std::string ioOp; + if (!sizeExprStr.empty()) + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); + else + ioOp = GetOpString(fieldName, propIdExpr); + + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << ioOp << ";\n" + << " return true;\n"; + } else if (!tsDecl->getName().compare("WString")) { + llvm::APSInt endian(64, -1); + std::string endianExprStr; + bool defaultEndian = true; + if (classParms->size() >= 2) { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + llvm::raw_string_ostream strStream(endianExprStr); + nttParm->print(strStream, context.getPrintingPolicy()); + } + } + + std::string sizeExprStr; + size_t idx = 0; + for (const clang::TemplateArgument& arg : *tsType) { + if (arg.getKind() == clang::TemplateArgument::Expression) { + const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); + if (idx == 0) { + llvm::APSInt sizeLiteral; + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + llvm::raw_string_ostream strStream2(sizeExprStr); + argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); + } else if (expr->isIntegerConstantExpr(sizeLiteral, context)) { + sizeExprStr = sizeLiteral.toString(10); + } + } else if (idx == 1) { + llvm::raw_string_ostream strStream(endianExprStr); + expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + defaultEndian = false; + } + } + ++idx; + } + + std::string ioOp; + if (!sizeExprStr.empty()) { + if (defaultEndian) + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); + else + ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); + } else { + if (defaultEndian) + ioOp = GetOpString(fieldName, propIdExpr); + else + ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); + } + + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << ioOp << ";\n" + << " return true;\n"; + } 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)) { + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" + << " return true;\n"; + } + } + } + } + + else if (regType->getTypeClass() == clang::Type::Record) { + const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); + std::string baseDNA; + if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) { + fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" + << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" + << " return true;\n"; + } + } + } + + fileOut << " default:\n return false;\n }\n}\n\n"; + } + +public: + explicit ATDNAEmitVisitor(clang::ASTContext& ctxin, StreamOut& fo) : context(ctxin), fileOut(fo) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) { + if (!EmitIncludes && !context.getSourceManager().isInMainFile(decl->getLocation())) + return true; + + if (decl->isInvalidDecl() || !decl->hasDefinition() || !decl->isCompleteDefinition()) + return true; + + if (!decl->getNumBases()) + return true; + + /* First ensure this inherits from struct athena::io::DNA */ + std::string baseDNA; + if (!isDNARecord(decl, baseDNA)) + return true; + + /* Determine if is is a YAML DNA */ + bool isYamlDNA = false; + for (const clang::CXXMethodDecl* method : decl->methods()) + if (method->getDeclName().isIdentifier() && + (!method->getName().compare(llvm::StringLiteral("read")) || + !method->getName().compare(llvm::StringLiteral("write"))) && + method->getNumParams() == 1 && + method->getParamDecl(0)->getType().getAsString() == "athena::io::YAMLDocReader &") { + isYamlDNA = true; + break; + } + + /* Determine if this is a regular DNA or PropDNA */ + bool isPropDNA = false; + for (const clang::Decl* d : decl->decls()) + if (const clang::FunctionTemplateDecl* m = clang::dyn_cast_or_null(d)) + if (m->getDeclName().isIdentifier() && !m->getName().compare(llvm::StringLiteral("Lookup"))) { + isPropDNA = true; + break; + } + + /* Make sure there isn't Delete meta type */ + for (const clang::FieldDecl* field : decl->fields()) { + clang::QualType qualType = field->getType().getCanonicalType(); + const clang::Type* regType = qualType.getTypePtrOrNull(); + if (regType) { + const clang::CXXRecordDecl* rDecl = regType->getAsCXXRecordDecl(); + if (rDecl) { + if (!rDecl->getName().compare("Delete")) { + const clang::CXXRecordDecl* rParentDecl = llvm::dyn_cast_or_null(rDecl->getParent()); + if (rParentDecl) { + std::string parentCheck = rParentDecl->getTypeForDecl()->getCanonicalTypeInternal().getAsString(); + if (!parentCheck.compare(0, sizeof(ATHENA_DNA_BASETYPE) - 1, ATHENA_DNA_BASETYPE)) + return true; + } + } + } + } + } + + std::vector> specializations = GetNestedTypeSpecializations(decl); + + emitEnumerateFunc(decl, baseDNA); + if (isPropDNA) { + emitLookupFunc(decl, baseDNA); + for (const auto& specialization : specializations) + fileOut << "AT_SPECIALIZE_PROPDNA(" << specialization.first << ")\n"; + } else if (isYamlDNA) { + for (const auto& specialization : specializations) + fileOut << "AT_SPECIALIZE_DNA_YAML(" << specialization.first << ")\n"; + } else { + for (const auto& specialization : specializations) + fileOut << "AT_SPECIALIZE_DNA(" << specialization.first << ")\n"; + } + fileOut << "\n\n"; + + for (const auto& specialization : specializations) { + for (int i = 0; i < specialization.second; ++i) + fileOut << "template <>\n"; + fileOut << "const char* " << specialization.first << "::DNAType()\n{\n return \"" << specialization.first + << "\";\n}\n"; + } + fileOut << "\n\n"; + + return true; + } +}; + +class ATDNAConsumer : public clang::ASTConsumer { + std::unique_ptr fileOut; + StreamOut& fileOutOld; + ATDNAEmitVisitor emitVisitor; + +public: + explicit ATDNAConsumer(clang::ASTContext& context, std::unique_ptr&& fo, StreamOut* foOld) + : fileOut(std::move(fo)), fileOutOld(*foOld), emitVisitor(context, *foOld) {} + + void HandleTranslationUnit(clang::ASTContext& context) override { + /* Write file head */ + fileOutOld << "/* Auto generated atdna implementation */\n" + "#include \"athena/DNAOp.hpp\"\n"; + for (const std::string& inputf : InputFilenames) + fileOutOld << "#include \"" << inputf << "\"\n"; + fileOutOld << "\n"; + + /* Emit file */ + emitVisitor.TraverseDecl(context.getTranslationUnitDecl()); + } +}; + +class ATDNAAction : public clang::ASTFrontendAction { + /* Used by LLVM 3.9+; client owns stream */ + std::unique_ptr MakeStreamOut(std::unique_ptr&& so, StreamOut*& outPtr) { + outPtr = so.get(); + return std::move(so); + } + + /* Used by previous versions of LLVM; CompilerInstance owns stream */ + std::unique_ptr MakeStreamOut(StreamOut* so, StreamOut*& outPtr) { + outPtr = so; + return {}; + } + + std::unique_ptr TheDependencyFileGenerator; + +public: + explicit ATDNAAction() = default; + std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, + llvm::StringRef /*filename*/) override { + clang::DependencyOutputOptions DepOpts; + DepOpts.OutputFile = DepFileOut.getValue(); + DepOpts.Targets = DepFileTargets; + if (!DepOpts.OutputFile.empty()) + TheDependencyFileGenerator.reset( + clang::DependencyFileGenerator::CreateAndAttachToPreprocessor(compiler.getPreprocessor(), DepOpts)); + + std::unique_ptr fileout; + StreamOut* fileoutOld; + if (OutputFilename.size()) + fileout = MakeStreamOut(compiler.createOutputFile(OutputFilename, false, true, "", "", true), fileoutOld); + else + fileout = MakeStreamOut(compiler.createDefaultOutputFile(false, "a", "cpp"), fileoutOld); + AthenaError = + compiler.getASTContext().getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Athena error: %0"); + return std::unique_ptr( + new ATDNAConsumer(compiler.getASTContext(), std::move(fileout), fileoutOld)); + } +}; + +int main(int argc, const char** argv) { + llvm::cl::ParseCommandLineOptions(argc, argv, "Athena DNA Generator"); + if (Help) + llvm::cl::PrintHelpMessage(); + + std::vector args = {"clang-tool", +#ifdef __linux__ + "--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]); + + llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); + ATDNAAction* action = new ATDNAAction(); + clang::tooling::ToolInvocation TI(args, action, fman.get()); + if (!TI.run()) + return 1; + + return 0; } diff --git a/atdna/test.cpp b/atdna/test.cpp index e1b5189..f23c929 100644 --- a/atdna/test.cpp +++ b/atdna/test.cpp @@ -3,22 +3,21 @@ #define EXPECTED_BYTES 281 -int main(int argc, const char** argv) -{ - TESTFile file = {}; - file.arrCount[0] = 2; - file.array.push_back(42); - file.array.push_back(64); - size_t binSize = 0; - file.binarySize(binSize); - athena::io::MemoryCopyWriter w(nullptr, binSize); - atInt64 pos = w.position(); - file.write(w); - bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES; - if (pass) - printf("[PASS] %" PRISize " bytes written\n", size_t(w.position() - pos)); - else - printf("[FAIL] %" PRISize " bytes written; %" PRISize " bytes sized; %d bytes expected\n", - size_t(w.position() - pos), binSize, EXPECTED_BYTES); - return pass ? 0 : 1; +int main(int argc, const char** argv) { + TESTFile file = {}; + file.arrCount[0] = 2; + file.array.push_back(42); + file.array.push_back(64); + size_t binSize = 0; + file.binarySize(binSize); + athena::io::MemoryCopyWriter w(nullptr, binSize); + atInt64 pos = w.position(); + file.write(w); + bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES; + if (pass) + printf("[PASS] %" PRISize " bytes written\n", size_t(w.position() - pos)); + else + printf("[FAIL] %" PRISize " bytes written; %" PRISize " bytes sized; %d bytes expected\n", + size_t(w.position() - pos), binSize, EXPECTED_BYTES); + return pass ? 0 : 1; } diff --git a/atdna/test.hpp b/atdna/test.hpp index 1ee8f19..608c2b1 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -3,87 +3,71 @@ using namespace athena; typedef io::DNA BigDNA; -enum ETest : atUint8 -{ - ZERO, - ONE, - TWO, - THREE -}; +enum ETest : atUint8 { ZERO, ONE, TWO, THREE }; template -struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE) -TESTSubFile : public BigDNA -{ - AT_DECL_DNA - Value varE = EVal; - Value sub1; - Value sub2; +struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE) TESTSubFile : public BigDNA { + AT_DECL_DNA + Value varE = EVal; + Value sub1; + Value sub2; }; -struct TESTSubClassFile : public TESTSubFile -{ - AT_DECL_DNA - Value sub3; - Value sub4; +struct TESTSubClassFile : public TESTSubFile { + AT_DECL_DNA + Value sub3; + Value sub4; }; -struct TESTSubSubClassFile : public TESTSubClassFile -{ - AT_DECL_DNA - Value sub5; - Value sub6; +struct TESTSubSubClassFile : public TESTSubClassFile { + AT_DECL_DNA + Value sub5; + Value sub6; }; template -struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) -TESTFile : public BigDNA -{ +struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) TESTFile : public BigDNA { + AT_DECL_DNA + Value varBool; + AT_OVERRIDE_RCRC32(12345678) Value x4_var32 = Var32Val; + AT_OVERRIDE_RCRC32(deadbabe) Value x8_var16; + Value vec3; + Value vec4; + + struct TESTNestedSubFile : public BigDNA { AT_DECL_DNA - Value varBool; - AT_OVERRIDE_RCRC32(12345678) Value x4_var32 = Var32Val; - AT_OVERRIDE_RCRC32(deadbabe) Value x8_var16; - Value vec3; - Value vec4; + Value nestSub1; + Value nestSub2; + } nestedSubFile; - struct TESTNestedSubFile : public BigDNA - { - AT_DECL_DNA - Value nestSub1; - Value nestSub2; - } nestedSubFile; + using TESTSubFileUsing = TESTSubFile; + TESTSubFileUsing subFile; - using TESTSubFileUsing = TESTSubFile; - TESTSubFileUsing subFile; + Align<4> align; - Align<4> align; + template + struct AT_SPECIALIZE_PARMS(atInt32, 36, atInt64, 96) TESTTemplateSubFile : public BigDNA { + AT_DECL_DNA + Value explSub1 = NestedVal; + Value explSub2 = Var32Val; + }; + Value> nestedTemplate1; + Value> nestedTemplate2; - template - struct AT_SPECIALIZE_PARMS(atInt32, 36, atInt64, 96) - TESTTemplateSubFile : public BigDNA - { - AT_DECL_DNA - Value explSub1 = NestedVal; - Value explSub2 = Var32Val; - }; - Value> nestedTemplate1; - Value> nestedTemplate2; + Value arrCount[2]; + Vector array; - Value arrCount[2]; - Vector array; + Value arrAltCount; + Vector arrayAlt; - Value arrAltCount; - Vector arrayAlt; + Seek<21, Current> seek; - Seek<21, Current> seek; + Value arrCount2; + Vector, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2; - Value arrCount2; - Vector, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2; + Value bufSz; + Buffer buf; - Value bufSz; - Buffer buf; - - String<32> str; - WString<64> wstr; + String<32> str; + WString<64> wstr; }; - diff --git a/include/LZ77/LZBase.hpp b/include/LZ77/LZBase.hpp index d16a1c9..74d244e 100644 --- a/include/LZ77/LZBase.hpp +++ b/include/LZ77/LZBase.hpp @@ -3,40 +3,38 @@ #include #include "LZ77/LZLookupTable.hpp" -class LZBase -{ +class LZBase { public: - explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3, atInt32 blockSize = 8); - virtual ~LZBase() {} + explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3, + atInt32 blockSize = 8); + virtual ~LZBase() {} - virtual atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; - virtual atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; - - void setSlidingWindow(atInt32 SlidingWindow); - atInt32 slidingWindow(); - void setReadAheadBuffer(atInt32 ReadAheadBuffer); - atInt32 readAheadBuffer(); - void setMinMatch(atInt32 minimumMatch); - atInt32 minMatch(); - void setBlockSize(atInt32 BlockSize); - atInt32 blockSize(); - void setMinimumOffset(atUint32 minimumOffset); - atUint32 minimumOffset(); + virtual atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; + virtual atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; + void setSlidingWindow(atInt32 SlidingWindow); + atInt32 slidingWindow(); + void setReadAheadBuffer(atInt32 ReadAheadBuffer); + atInt32 readAheadBuffer(); + void setMinMatch(atInt32 minimumMatch); + atInt32 minMatch(); + void setBlockSize(atInt32 BlockSize); + atInt32 blockSize(); + void setMinimumOffset(atUint32 minimumOffset); + atUint32 minimumOffset(); private: + atInt32 subMatch(const atUint8* str1, const uint8_t* str2, const atInt32 len); + LZLengthOffset windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, + atUint8* startLBPtr); - atInt32 subMatch(const atUint8* str1, const uint8_t* str2, const atInt32 len); - LZLengthOffset windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, atUint8* startLBPtr); protected: - LZLengthOffset search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd); - - atInt32 m_slidingWindow; - atInt32 m_readAheadBuffer; - atInt32 m_minMatch;//Minimum number of bytes that have to matched to go through with compression - atInt32 m_blockSize; - atUint32 m_minOffset; - LZLookupTable m_lookupTable; + LZLengthOffset search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd); + atInt32 m_slidingWindow; + atInt32 m_readAheadBuffer; + atInt32 m_minMatch; // Minimum number of bytes that have to matched to go through with compression + atInt32 m_blockSize; + atUint32 m_minOffset; + LZLookupTable m_lookupTable; }; - diff --git a/include/LZ77/LZLookupTable.hpp b/include/LZ77/LZLookupTable.hpp index 325eb7d..61bfb9e 100644 --- a/include/LZ77/LZLookupTable.hpp +++ b/include/LZ77/LZLookupTable.hpp @@ -6,32 +6,25 @@ #include #include -struct LZLengthOffset -{ - atUint32 length;//The number of bytes compressed - atUint16 offset;//How far back in sliding window where bytes that match the lookAheadBuffer is located - bool compare_equal(const LZLengthOffset& lo_pair) - { - return length == lo_pair.length && offset == lo_pair.offset; - } +struct LZLengthOffset { + atUint32 length; // The number of bytes compressed + atUint16 offset; // How far back in sliding window where bytes that match the lookAheadBuffer is located + bool compare_equal(const LZLengthOffset& lo_pair) { return length == lo_pair.length && offset == lo_pair.offset; } }; -class LZLookupTable -{ +class LZLookupTable { public: - LZLookupTable(); - LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18); - ~LZLookupTable(); - LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd); - void setLookAheadWindow(atInt32 lookAheadWindow); + LZLookupTable(); + LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18); + ~LZLookupTable(); + LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd); + void setLookAheadWindow(atInt32 lookAheadWindow); + private: - typedef std::multimap, int32_t> LookupTable; - LookupTable table; - atInt32 m_minimumMatch; - atInt32 m_slidingWindow; - atInt32 m_lookAheadWindow; - std::vector m_buffer; - - + typedef std::multimap, int32_t> LookupTable; + LookupTable table; + atInt32 m_minimumMatch; + atInt32 m_slidingWindow; + atInt32 m_lookAheadWindow; + std::vector m_buffer; }; - diff --git a/include/LZ77/LZType10.hpp b/include/LZ77/LZType10.hpp index b914769..d27df33 100644 --- a/include/LZ77/LZType10.hpp +++ b/include/LZ77/LZType10.hpp @@ -2,11 +2,10 @@ #include "LZBase.hpp" -class LZType10 : public LZBase -{ +class LZType10 : public LZBase { public: - explicit LZType10(atInt32 minimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, atInt32 BlockSize = 8); - atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength); - atUint32 decompress(const atUint8* src, atUint8** dst, atUint32 srcLen); + explicit LZType10(atInt32 minimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, + atInt32 BlockSize = 8); + atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength); + atUint32 decompress(const atUint8* src, atUint8** dst, atUint32 srcLen); }; - diff --git a/include/LZ77/LZType11.hpp b/include/LZ77/LZType11.hpp index 7673140..23d2501 100644 --- a/include/LZ77/LZType11.hpp +++ b/include/LZ77/LZType11.hpp @@ -1,14 +1,11 @@ #pragma once - #include "LZBase.hpp" -class LZType11 : public LZBase -{ +class LZType11 : public LZBase { public: - explicit LZType11(atInt32 MinimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, atInt32 BlockSize = 8); - atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength); - atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength); - + explicit LZType11(atInt32 MinimumOffset = 1, atInt32 SlidingWindow = 4096, atInt32 MinimumMatch = 3, + atInt32 BlockSize = 8); + atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength); + atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength); }; - diff --git a/include/aes.hpp b/include/aes.hpp index 20a2917..e35bce2 100644 --- a/include/aes.hpp +++ b/include/aes.hpp @@ -4,19 +4,16 @@ #include #include -namespace athena -{ +namespace athena { -class IAES -{ +class IAES { public: - virtual ~IAES() {} - virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0; - virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0; - virtual void setKey(const uint8_t* key)=0; + virtual ~IAES() {} + virtual void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) = 0; + virtual void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) = 0; + virtual void setKey(const uint8_t* key) = 0; }; std::unique_ptr NewAES(); -} - +} // namespace athena diff --git a/include/athena/ALTTPEnums.hpp b/include/athena/ALTTPEnums.hpp index 72df124..4dcf6d8 100644 --- a/include/athena/ALTTPEnums.hpp +++ b/include/athena/ALTTPEnums.hpp @@ -2,92 +2,56 @@ #include "Types.hpp" -namespace athena -{ +namespace athena { -enum BowType : char -{ - BowNone, - BowArrows, - BowSilverArrows +enum BowType : char { BowNone, BowArrows, BowSilverArrows }; + +enum BoomerangType : char { BoomerangNone, BoomerangBlue, BoomerangRed }; + +enum MagicType : char { MagicNone, MagicMushroom, MagicPowder }; + +enum ArmorType : char { GreenJerkin, BlueMail, RedMail }; + +enum BottleType : char { + BottleNone, + BottleMushroom, // No Use + BottleEmpty, + BottleRedPotion, + BottleBluePotion, + BottleFairy, + BottleBee, + BottleGoodBee }; -enum BoomerangType : char -{ - BoomerangNone, - BoomerangBlue, - BoomerangRed +enum ALTTPStartLocation { LinksHouse = 0x00, Sanctuary = 0x01, Any = 0x05 }; + +enum ALTTPProgressIndicator { LinkInBed, InCastleWithSword, CompletedFirstDungeon, BeatenAghanim }; + +enum ALTTPMapIcon { + Nothing = 0x00, //? + CrossInKakariko = 0x01, //? + CrossAtFirstDungeon = 0x02, // + Pendant = 0x03, + MasterSword = 0x04, + AganhimCastle = 0x05, + Crystal1 = 0x06, + AllCrystals = 0x07, + AganhimGanonTower = 0x08 }; -enum MagicType : char -{ - MagicNone, - MagicMushroom, - MagicPowder +enum ALTTPTagAlong { + Noone, + Zelda, + Unknown1, + Oldman, + ZeldaMessage, + Blind, + DwarfFrog, + DwarfLW, + Kiki, + Unknown2, + TheifsChest, + AfterBoss }; -enum ArmorType : char -{ - GreenJerkin, - BlueMail, - RedMail -}; - -enum BottleType : char -{ - BottleNone, - BottleMushroom, // No Use - BottleEmpty, - BottleRedPotion, - BottleBluePotion, - BottleFairy, - BottleBee, - BottleGoodBee -}; - - -enum ALTTPStartLocation -{ - LinksHouse = 0x00, - Sanctuary = 0x01, - Any = 0x05 -}; - -enum ALTTPProgressIndicator -{ - LinkInBed, - InCastleWithSword, - CompletedFirstDungeon, - BeatenAghanim -}; - -enum ALTTPMapIcon -{ - Nothing = 0x00, //? - CrossInKakariko = 0x01, //? - CrossAtFirstDungeon = 0x02, // - Pendant = 0x03, - MasterSword = 0x04, - AganhimCastle = 0x05, - Crystal1 = 0x06, - AllCrystals = 0x07, - AganhimGanonTower = 0x08 -}; - -enum ALTTPTagAlong -{ - Noone, - Zelda, - Unknown1, - Oldman, - ZeldaMessage, - Blind, - DwarfFrog, - DwarfLW, - Kiki, - Unknown2, - TheifsChest, - AfterBoss -}; - -} // zelda +} // namespace athena diff --git a/include/athena/ALTTPFile.hpp b/include/athena/ALTTPFile.hpp index ea92207..70be97a 100644 --- a/include/athena/ALTTPFile.hpp +++ b/include/athena/ALTTPFile.hpp @@ -3,8 +3,7 @@ #include "athena/Global.hpp" #include -namespace athena -{ +namespace athena { class ALTTPQuest; @@ -14,61 +13,58 @@ class ALTTPQuest; * Contains all relevant data for an A Link to the Past * SRM file. */ -class ALTTPFile -{ +class ALTTPFile { public: - /*! \brief Quest Iterator - * - * An Iterator typedef for iterating through the Quest lists - */ - typedef std::vector::iterator QuestIter; + /*! \brief Quest Iterator + * + * An Iterator typedef for iterating through the Quest lists + */ + typedef std::vector::iterator QuestIter; - /*! \brief Default constructor - * - * - */ - ALTTPFile(); + /*! \brief Default constructor + * + * + */ + ALTTPFile(); - /*! \brief Constructor - * - * \param questList The primary quest list - * \param backupList The backup quest list - */ - ALTTPFile(std::vector questList, std::vector backupList); + /*! \brief Constructor + * + * \param questList The primary quest list + * \param backupList The backup quest list + */ + ALTTPFile(std::vector questList, std::vector backupList); + /*! \brief Sets a quest at the given index + * + * \param id Index to the given quest + * \param val The new quest to assign to the given index + * \throw InvalidOperationException on index out of range + */ + void setQuest(atUint32 id, ALTTPQuest* val); + /*! \brief Returns the primary quest list + * + * \return The primary quest list + */ + std::vector questList() const; - /*! \brief Sets a quest at the given index - * - * \param id Index to the given quest - * \param val The new quest to assign to the given index - * \throw InvalidOperationException on index out of range - */ - void setQuest(atUint32 id, ALTTPQuest* val); - /*! \brief Returns the primary quest list - * - * \return The primary quest list - */ - std::vector questList() const; + /*! \brief Returns a quest at the given index + * + * Returns a quest at the given index + * + * \return ALTTPQuest* + * \throw InvalidOperationException on index out of range + */ + ALTTPQuest* quest(atUint32 id) const; - /*! \brief Returns a quest at the given index - * - * Returns a quest at the given index - * - * \return ALTTPQuest* - * \throw InvalidOperationException on index out of range - */ - ALTTPQuest* quest(atUint32 id) const; - - /*! \brief Returns the number of primary quests - * - * \return The number of quests - */ - atUint32 questCount() const; + /*! \brief Returns the number of primary quests + * + * \return The number of quests + */ + atUint32 questCount() const; private: - - std::vector m_quests; - std::vector m_backup; + std::vector m_quests; + std::vector m_backup; }; -} // zelda +} // namespace athena diff --git a/include/athena/ALTTPFileReader.hpp b/include/athena/ALTTPFileReader.hpp index 80679d4..c3af63e 100644 --- a/include/athena/ALTTPFileReader.hpp +++ b/include/athena/ALTTPFileReader.hpp @@ -5,12 +5,10 @@ #include "athena/MemoryReader.hpp" #include "athena/ALTTPQuest.hpp" -namespace athena -{ +namespace athena { class ALTTPFile; -namespace io -{ +namespace io { /*! \class ALTTPFileReader * \brief A Link to the Past save data reader class * @@ -18,32 +16,32 @@ namespace io * all work is done using a memory buffer, and not read directly from the disk. * \sa BinaryReader */ -class ALTTPFileReader : protected MemoryCopyReader -{ +class ALTTPFileReader : protected MemoryCopyReader { public: - /*! \brief This constructor takes an existing buffer to read from. - * - * \param data The existing buffer - * \param length The length of the existing buffer - */ - ALTTPFileReader(atUint8*, atUint64); + /*! \brief This constructor takes an existing buffer to read from. + * + * \param data The existing buffer + * \param length The length of the existing buffer + */ + ALTTPFileReader(atUint8*, atUint64); - /*! \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - ALTTPFileReader(const std::string&); + /*! \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + ALTTPFileReader(const std::string&); + + /*! \brief Reads the SRAM data from the buffer + * + * \return ALTTPFile* SRAM data + */ + ALTTPFile* readFile(); - /*! \brief Reads the SRAM data from the buffer - * - * \return ALTTPFile* SRAM data - */ - ALTTPFile* readFile(); private: - ALTTPRoomFlags* readRoomFlags(); - ALTTPOverworldEvent* readOverworldEvent(); - ALTTPDungeonItemFlags readDungeonFlags(); + ALTTPRoomFlags* readRoomFlags(); + ALTTPOverworldEvent* readOverworldEvent(); + ALTTPDungeonItemFlags readDungeonFlags(); }; -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/include/athena/ALTTPFileWriter.hpp b/include/athena/ALTTPFileWriter.hpp index 9e5dc11..d1b4aa5 100644 --- a/include/athena/ALTTPFileWriter.hpp +++ b/include/athena/ALTTPFileWriter.hpp @@ -4,12 +4,10 @@ #include "athena/MemoryWriter.hpp" #include "athena/ALTTPQuest.hpp" -namespace athena -{ +namespace athena { class ALTTPFile; -namespace io -{ +namespace io { /*! \class ALTTPFileWriter * \brief A Link to the Past save data writer class * @@ -17,35 +15,33 @@ namespace io * all work is done using a memory buffer, and not written directly to the disk. * \sa BinaryReader */ -class ALTTPFileWriter : protected MemoryCopyWriter -{ +class ALTTPFileWriter : protected MemoryCopyWriter { public: - /*! \brief This constructor takes an existing buffer to write to. - * - * \param data The existing buffer - * \param length The length of the existing buffer - */ - ALTTPFileWriter(atUint8*, atUint64); + /*! \brief This constructor takes an existing buffer to write to. + * + * \param data The existing buffer + * \param length The length of the existing buffer + */ + ALTTPFileWriter(atUint8*, atUint64); - /*! \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - ALTTPFileWriter(const std::string&); + /*! \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + ALTTPFileWriter(const std::string&); - /*! \brief Writes the given SRAM data to a file on disk - * - * \param file SRAM data to right - */ - void writeFile(ALTTPFile* file); + /*! \brief Writes the given SRAM data to a file on disk + * + * \param file SRAM data to right + */ + void writeFile(ALTTPFile* file); private: - void writeRoomFlags(ALTTPRoomFlags*); - void writeOverworldEvent(ALTTPOverworldEvent*); - void writeDungeonItems(ALTTPDungeonItemFlags); - atUint16 calculateChecksum(atUint32 game); + void writeRoomFlags(ALTTPRoomFlags*); + void writeOverworldEvent(ALTTPOverworldEvent*); + void writeDungeonItems(ALTTPDungeonItemFlags); + atUint16 calculateChecksum(atUint32 game); }; -} // io -} // zelda - +} // namespace io +} // namespace athena diff --git a/include/athena/ALTTPQuest.hpp b/include/athena/ALTTPQuest.hpp index fdc0248..c9a6fb4 100644 --- a/include/athena/ALTTPQuest.hpp +++ b/include/athena/ALTTPQuest.hpp @@ -6,8 +6,7 @@ #include "athena/ALTTPStructs.hpp" #include "athena/ALTTPEnums.hpp" -namespace athena -{ +namespace athena { /*! \class ALTTPQuest * \brief A Link to the Past Quest container class @@ -15,656 +14,654 @@ namespace athena * Contains all relevant data for an A Link to the Past * Quest entry. */ -class ALTTPQuest -{ +class ALTTPQuest { public: - /*! - * \brief ALTTPQuest - */ - ALTTPQuest(); - ~ALTTPQuest(); - - /*! - * \brief setRoomFlags - * \param flags - */ - void setRoomFlags(std::vector flags); - - /*! - * \brief setRoomFlags - * \param rf - * \param id - */ - void setRoomFlags(ALTTPRoomFlags* rf, atUint32 id); - - /*! - * \brief roomFlags - * \return - */ - std::vector roomFlags(); - - /*! - * \brief roomFlags - * \param id - * \return - */ - ALTTPRoomFlags* roomFlags(atUint32 id); - - /*! - * \brief setOverworldEvents - * \param events - */ - void setOverworldEvents(std::vector events); - - /*! - * \brief setOverworldEvents - * \param ow - * \param id - */ - void setOverworldEvents(ALTTPOverworldEvent* ow, atUint32 id); - - /*! - * \brief overworldEvents - * \return - */ - std::vector overworldEvents() const; - - /*! - * \brief overworldEvent - * \param id - * \return - */ - ALTTPOverworldEvent* overworldEvent(atUint32 id) const; - - /*! - * \brief setInventory - * \param inv - */ - void setInventory(const ALTTPInventory& inv); - - /*! - * \brief inventory - * \return - */ - const ALTTPInventory& inventory() const; - - /*! - * \brief setRupeeMax - * \param val - */ - void setRupeeMax(atUint16 val); - - /*! - * \brief rupeeMax - * \return - */ - atUint16 rupeeMax() const; - - /*! - * \brief setRupeeCurrent - * \param val - */ - void setRupeeCurrent(atUint16 val); - - /*! - * \brief rupeeCurrent - * \return - */ - atUint16 rupeeCurrent() const; - - /*! - * \brief setCompasses - * \param flags - */ - void setCompasses(ALTTPDungeonItemFlags flags); - - /*! - * \brief compasses - * \return - */ - ALTTPDungeonItemFlags compasses() const; - - /*! - * \brief setBigKeys - * \param flags - */ - void setBigKeys(ALTTPDungeonItemFlags flags); - - /*! - * \brief bigKeys - * \return - */ - ALTTPDungeonItemFlags bigKeys() const; - - /*! - * \brief setDungeonMaps - * \param flags - */ - void setDungeonMaps(ALTTPDungeonItemFlags flags); - - /*! - * \brief dungeonMaps - * \return - */ - ALTTPDungeonItemFlags dungeonMaps() const; - - /*! - * \brief setWishingPond - * \param val - */ - void setWishingPond(atUint16 val); - - /*! - * \brief wishingPond - * \return - */ - atUint16 wishingPond() const; - - /*! - * \brief setHealthMax - * \param val - */ - void setHealthMax(atUint8 val); - - /*! - * \brief healthMax - * \return - */ - atUint8 healthMax() const; - - /*! - * \brief setHealth - * \param val - */ - void setHealth(atUint8 val); - - /*! - * \brief health - * \return - */ - atUint8 health() const; - - /*! - * \brief setMagicPower - * \param val - */ - void setMagicPower(atUint8 val); - - /*! - * \brief magicPower - * \return - */ - atUint8 magicPower() const; - - /*! - * \brief setKeys - * \param val - */ - void setKeys(atUint8 val); - - /*! - * \brief keys - * \return - */ - atUint8 keys() const; - - /*! - * \brief setBombUpgrades - * \param val - */ - void setBombUpgrades(atUint8 val); - - /*! - * \brief bombUpgrades - * \return - */ - atUint8 bombUpgrades() const; - - /*! - * \brief setArrowUpgrades - * \param val - */ - void setArrowUpgrades(atUint8 val); - - /*! - * \brief arrowUpgrades - * \return - */ - atUint8 arrowUpgrades() const; - - /*! - * \brief setHealthFiller - * \param val - */ - void setHealthFiller(atUint8 val); - - /*! - * \brief healthFiller - * \return - */ - atUint8 healthFiller() const; - - /*! - * \brief setMagicFiller - * \param val - */ - void setMagicFiller(atUint8 val); - - /*! - * \brief magicFiller - * \return - */ - atUint8 magicFiller() const; - - /*! - * \brief setPendants - * \param val - */ - void setPendants(ALTTPPendants val); - - /*! - * \brief pendants - * \return - */ - ALTTPPendants pendants() const; - - /*! - * \brief setBombFiller - * \param val - */ - void setBombFiller(atUint8 val); - - /*! - * \brief bombFiller - * \return - */ - atUint8 bombFiller() const; - - /*! - * \brief setArrowFiller - * \param val - */ - void setArrowFiller(atUint8 val); - - /*! - * \brief arrowFiller - * \return - */ - atUint8 arrowFiller() const; - - /*! - * \brief setArrows - * \param val - */ - void setArrows(atUint8 val); - - /*! - * \brief arrows - * \return - */ - atUint8 arrows() const; - - /*! - * \brief setAbilityFlags - * \param val - */ - void setAbilityFlags(ALTTPAbilities val); - - /*! - * \brief abilityFlags - * \return - */ - ALTTPAbilities abilityFlags() const; - - /*! - * \brief setCrystals - * \param val - */ - void setCrystals(ALTTPCrystals val); - \ - - /*! - * \brief crystals - * \return - */ - ALTTPCrystals crystals() const; - - /*! - * \brief setMagicUsage - * \param val - */ - void setMagicUsage(ALTTPMagicUsage val); - - /*! - * \brief magicUsage - * \return - */ - ALTTPMagicUsage magicUsage() const; - - /*! - * \brief setDungeonKeys - * \param val - */ - void setDungeonKeys(std::vector val); - - /*! - * \brief setDungeonKeys - * \param id - * \param val - */ - void setDungeonKeys(atUint32 id, atUint8 val); - - /*! - * \brief dungeonKeys - * \param id - * \return - */ - atUint8 dungeonKeys(atUint32 id) const; - - /*! - * \brief dungeonCount - * \return - */ - atUint32 dungeonCount() const; - - /*! - * \brief setProgressIndicator - * \param val - */ - void setProgressIndicator(ALTTPProgressIndicator val); - - /*! - * \brief progressIndicator - * \return - */ - ALTTPProgressIndicator progressIndicator() const; - - /*! - * \brief setProgressFlags1 - * \param val - */ - void setProgressFlags1(ALTTPProgressFlags1 val); - - /*! - * \brief progressFlags1 - * \return - */ - ALTTPProgressFlags1 progressFlags1() const; - - /*! - * \brief setMapIcon - * \param val - */ - void setMapIcon(ALTTPMapIcon val); - - /*! - * \brief mapIcon - * \return - */ - ALTTPMapIcon mapIcon() const; - - /*! - * \brief setStartLocation - * \param val - */ - void setStartLocation(ALTTPStartLocation val); - - /*! - * \brief startLocation - * \return - */ - ALTTPStartLocation startLocation() const; - - /*! - * \brief setProgressFlags2 - * \param val - */ - void setProgressFlags2(ALTTPProgressFlags2 val); - - /*! - * \brief progressFlags2 - * \return - */ - ALTTPProgressFlags2 progressFlags2() const; - - /*! - * \brief setLightDarkWorldIndicator - * \param val - */ - void setLightDarkWorldIndicator(ALTTPLightDarkWorldIndicator val); - - /*! - * \brief lightDarkWorldIndicator - * \return - */ - ALTTPLightDarkWorldIndicator lightDarkWorldIndicator() const; - - /*! - * \brief setTagAlong - * \param val - */ - void setTagAlong(ALTTPTagAlong val); - - /*! - * \brief tagAlong - * \return - */ - ALTTPTagAlong tagAlong() const; - - /*! - * \brief setOldManFlags - * \param flags - */ - void setOldManFlags(std::vector flags); - - /*! - * \brief setOldManFlag - * \param id - * \param val - */ - void setOldManFlag(atUint32 id, atUint8 val); - - /*! - * \brief oldManFlag - * \param id - * \return - */ - atUint8 oldManFlag(atUint32 id); - - /*! - * \brief oldManFlagCount - * \return - */ - atUint32 oldManFlagCount() const; - - /*! - * \brief setBombFlag - * \param flag - */ - void setBombFlag(atUint8 flag); - - /*! - * \brief bombFlag - * \return - */ - atUint8 bombFlag() const; - - /*! - * \brief setUnknown1 - * \param flags - */ - void setUnknown1(std::vector flags); - - /*! - * \brief setUnknown1 - * \param id - * \param val - */ - void setUnknown1(atUint32 id, atUint8 val); - - /*! - * \brief unknown1 - * \param id - * \return - */ - atUint8 unknown1(atUint32 id); - - /*! - * \brief unknown1Count - * \return - */ - atUint32 unknown1Count() const; - - /*! - * \brief setPlayerName - * \param playerName - */ - void setPlayerName(std::vector playerName); - /*! - * \brief setPlayerName - * \param playerName - */ - void setPlayerName(const std::string& playerName); - /*! - * \brief playerName - * \return - */ - std::vector playerName() const; - /*! - * \brief playerNameToString - * \return - */ - std::string playerNameToString() const; - - /*! - * \brief setValid - * \param val - */ - void setValid(bool val); - - /*! - * \brief valid - * \return - */ - bool valid(); - - /*! - * \brief setDungeonDeathTotals - * \param val - */ - void setDungeonDeathTotals(std::vector val); - - /*! - * \brief setDungeonDeathTotal - * \param id - * \param val - */ - void setDungeonDeathTotal(atUint32 id, atUint16 val); - - /*! - * \brief dungeonDeathTotal - * \param id - * \return - */ - atUint16 dungeonDeathTotal(atUint32 id) const; - - /*! - * \brief dungeonDeathTotalCount - * \return - */ - atUint16 dungeonDeathTotalCount() const; - - /*! - * \brief setUnknown2 - * \param val - */ - void setUnknown2(atUint16 val); - - /*! - * \brief unknown2 - * \return - */ - atUint16 unknown2() const; - - /*! - * \brief setDeathSaveCount - * \param val - */ - void setDeathSaveCount(atUint16 val); - - /*! - * \brief deathSaveCount - * \return - */ - atUint16 deathSaveCount() const; - - /*! - * \brief setPostGameDeathCounter - * \param val - */ - void setPostGameDeathCounter(atInt16 val); - - /*! - * \brief postGameDeathCounter - * \return - */ - atInt16 postGameDeathCounter() const; - - /*! - * \brief setChecksum - * \param checksum - */ - void setChecksum(atUint16 checksum); - - /*! - * \brief checksum - * \return - */ - atUint16 checksum() const; + /*! + * \brief ALTTPQuest + */ + ALTTPQuest(); + ~ALTTPQuest(); + + /*! + * \brief setRoomFlags + * \param flags + */ + void setRoomFlags(std::vector flags); + + /*! + * \brief setRoomFlags + * \param rf + * \param id + */ + void setRoomFlags(ALTTPRoomFlags* rf, atUint32 id); + + /*! + * \brief roomFlags + * \return + */ + std::vector roomFlags(); + + /*! + * \brief roomFlags + * \param id + * \return + */ + ALTTPRoomFlags* roomFlags(atUint32 id); + + /*! + * \brief setOverworldEvents + * \param events + */ + void setOverworldEvents(std::vector events); + + /*! + * \brief setOverworldEvents + * \param ow + * \param id + */ + void setOverworldEvents(ALTTPOverworldEvent* ow, atUint32 id); + + /*! + * \brief overworldEvents + * \return + */ + std::vector overworldEvents() const; + + /*! + * \brief overworldEvent + * \param id + * \return + */ + ALTTPOverworldEvent* overworldEvent(atUint32 id) const; + + /*! + * \brief setInventory + * \param inv + */ + void setInventory(const ALTTPInventory& inv); + + /*! + * \brief inventory + * \return + */ + const ALTTPInventory& inventory() const; + + /*! + * \brief setRupeeMax + * \param val + */ + void setRupeeMax(atUint16 val); + + /*! + * \brief rupeeMax + * \return + */ + atUint16 rupeeMax() const; + + /*! + * \brief setRupeeCurrent + * \param val + */ + void setRupeeCurrent(atUint16 val); + + /*! + * \brief rupeeCurrent + * \return + */ + atUint16 rupeeCurrent() const; + + /*! + * \brief setCompasses + * \param flags + */ + void setCompasses(ALTTPDungeonItemFlags flags); + + /*! + * \brief compasses + * \return + */ + ALTTPDungeonItemFlags compasses() const; + + /*! + * \brief setBigKeys + * \param flags + */ + void setBigKeys(ALTTPDungeonItemFlags flags); + + /*! + * \brief bigKeys + * \return + */ + ALTTPDungeonItemFlags bigKeys() const; + + /*! + * \brief setDungeonMaps + * \param flags + */ + void setDungeonMaps(ALTTPDungeonItemFlags flags); + + /*! + * \brief dungeonMaps + * \return + */ + ALTTPDungeonItemFlags dungeonMaps() const; + + /*! + * \brief setWishingPond + * \param val + */ + void setWishingPond(atUint16 val); + + /*! + * \brief wishingPond + * \return + */ + atUint16 wishingPond() const; + + /*! + * \brief setHealthMax + * \param val + */ + void setHealthMax(atUint8 val); + + /*! + * \brief healthMax + * \return + */ + atUint8 healthMax() const; + + /*! + * \brief setHealth + * \param val + */ + void setHealth(atUint8 val); + + /*! + * \brief health + * \return + */ + atUint8 health() const; + + /*! + * \brief setMagicPower + * \param val + */ + void setMagicPower(atUint8 val); + + /*! + * \brief magicPower + * \return + */ + atUint8 magicPower() const; + + /*! + * \brief setKeys + * \param val + */ + void setKeys(atUint8 val); + + /*! + * \brief keys + * \return + */ + atUint8 keys() const; + + /*! + * \brief setBombUpgrades + * \param val + */ + void setBombUpgrades(atUint8 val); + + /*! + * \brief bombUpgrades + * \return + */ + atUint8 bombUpgrades() const; + + /*! + * \brief setArrowUpgrades + * \param val + */ + void setArrowUpgrades(atUint8 val); + + /*! + * \brief arrowUpgrades + * \return + */ + atUint8 arrowUpgrades() const; + + /*! + * \brief setHealthFiller + * \param val + */ + void setHealthFiller(atUint8 val); + + /*! + * \brief healthFiller + * \return + */ + atUint8 healthFiller() const; + + /*! + * \brief setMagicFiller + * \param val + */ + void setMagicFiller(atUint8 val); + + /*! + * \brief magicFiller + * \return + */ + atUint8 magicFiller() const; + + /*! + * \brief setPendants + * \param val + */ + void setPendants(ALTTPPendants val); + + /*! + * \brief pendants + * \return + */ + ALTTPPendants pendants() const; + + /*! + * \brief setBombFiller + * \param val + */ + void setBombFiller(atUint8 val); + + /*! + * \brief bombFiller + * \return + */ + atUint8 bombFiller() const; + + /*! + * \brief setArrowFiller + * \param val + */ + void setArrowFiller(atUint8 val); + + /*! + * \brief arrowFiller + * \return + */ + atUint8 arrowFiller() const; + + /*! + * \brief setArrows + * \param val + */ + void setArrows(atUint8 val); + + /*! + * \brief arrows + * \return + */ + atUint8 arrows() const; + + /*! + * \brief setAbilityFlags + * \param val + */ + void setAbilityFlags(ALTTPAbilities val); + + /*! + * \brief abilityFlags + * \return + */ + ALTTPAbilities abilityFlags() const; + + /*! + * \brief setCrystals + * \param val + */ + void setCrystals(ALTTPCrystals val); + + /*! + * \brief crystals + * \return + */ + ALTTPCrystals crystals() const; + + /*! + * \brief setMagicUsage + * \param val + */ + void setMagicUsage(ALTTPMagicUsage val); + + /*! + * \brief magicUsage + * \return + */ + ALTTPMagicUsage magicUsage() const; + + /*! + * \brief setDungeonKeys + * \param val + */ + void setDungeonKeys(std::vector val); + + /*! + * \brief setDungeonKeys + * \param id + * \param val + */ + void setDungeonKeys(atUint32 id, atUint8 val); + + /*! + * \brief dungeonKeys + * \param id + * \return + */ + atUint8 dungeonKeys(atUint32 id) const; + + /*! + * \brief dungeonCount + * \return + */ + atUint32 dungeonCount() const; + + /*! + * \brief setProgressIndicator + * \param val + */ + void setProgressIndicator(ALTTPProgressIndicator val); + + /*! + * \brief progressIndicator + * \return + */ + ALTTPProgressIndicator progressIndicator() const; + + /*! + * \brief setProgressFlags1 + * \param val + */ + void setProgressFlags1(ALTTPProgressFlags1 val); + + /*! + * \brief progressFlags1 + * \return + */ + ALTTPProgressFlags1 progressFlags1() const; + + /*! + * \brief setMapIcon + * \param val + */ + void setMapIcon(ALTTPMapIcon val); + + /*! + * \brief mapIcon + * \return + */ + ALTTPMapIcon mapIcon() const; + + /*! + * \brief setStartLocation + * \param val + */ + void setStartLocation(ALTTPStartLocation val); + + /*! + * \brief startLocation + * \return + */ + ALTTPStartLocation startLocation() const; + + /*! + * \brief setProgressFlags2 + * \param val + */ + void setProgressFlags2(ALTTPProgressFlags2 val); + + /*! + * \brief progressFlags2 + * \return + */ + ALTTPProgressFlags2 progressFlags2() const; + + /*! + * \brief setLightDarkWorldIndicator + * \param val + */ + void setLightDarkWorldIndicator(ALTTPLightDarkWorldIndicator val); + + /*! + * \brief lightDarkWorldIndicator + * \return + */ + ALTTPLightDarkWorldIndicator lightDarkWorldIndicator() const; + + /*! + * \brief setTagAlong + * \param val + */ + void setTagAlong(ALTTPTagAlong val); + + /*! + * \brief tagAlong + * \return + */ + ALTTPTagAlong tagAlong() const; + + /*! + * \brief setOldManFlags + * \param flags + */ + void setOldManFlags(std::vector flags); + + /*! + * \brief setOldManFlag + * \param id + * \param val + */ + void setOldManFlag(atUint32 id, atUint8 val); + + /*! + * \brief oldManFlag + * \param id + * \return + */ + atUint8 oldManFlag(atUint32 id); + + /*! + * \brief oldManFlagCount + * \return + */ + atUint32 oldManFlagCount() const; + + /*! + * \brief setBombFlag + * \param flag + */ + void setBombFlag(atUint8 flag); + + /*! + * \brief bombFlag + * \return + */ + atUint8 bombFlag() const; + + /*! + * \brief setUnknown1 + * \param flags + */ + void setUnknown1(std::vector flags); + + /*! + * \brief setUnknown1 + * \param id + * \param val + */ + void setUnknown1(atUint32 id, atUint8 val); + + /*! + * \brief unknown1 + * \param id + * \return + */ + atUint8 unknown1(atUint32 id); + + /*! + * \brief unknown1Count + * \return + */ + atUint32 unknown1Count() const; + + /*! + * \brief setPlayerName + * \param playerName + */ + void setPlayerName(std::vector playerName); + /*! + * \brief setPlayerName + * \param playerName + */ + void setPlayerName(const std::string& playerName); + /*! + * \brief playerName + * \return + */ + std::vector playerName() const; + /*! + * \brief playerNameToString + * \return + */ + std::string playerNameToString() const; + + /*! + * \brief setValid + * \param val + */ + void setValid(bool val); + + /*! + * \brief valid + * \return + */ + bool valid(); + + /*! + * \brief setDungeonDeathTotals + * \param val + */ + void setDungeonDeathTotals(std::vector val); + + /*! + * \brief setDungeonDeathTotal + * \param id + * \param val + */ + void setDungeonDeathTotal(atUint32 id, atUint16 val); + + /*! + * \brief dungeonDeathTotal + * \param id + * \return + */ + atUint16 dungeonDeathTotal(atUint32 id) const; + + /*! + * \brief dungeonDeathTotalCount + * \return + */ + atUint16 dungeonDeathTotalCount() const; + + /*! + * \brief setUnknown2 + * \param val + */ + void setUnknown2(atUint16 val); + + /*! + * \brief unknown2 + * \return + */ + atUint16 unknown2() const; + + /*! + * \brief setDeathSaveCount + * \param val + */ + void setDeathSaveCount(atUint16 val); + + /*! + * \brief deathSaveCount + * \return + */ + atUint16 deathSaveCount() const; + + /*! + * \brief setPostGameDeathCounter + * \param val + */ + void setPostGameDeathCounter(atInt16 val); + + /*! + * \brief postGameDeathCounter + * \return + */ + atInt16 postGameDeathCounter() const; + + /*! + * \brief setChecksum + * \param checksum + */ + void setChecksum(atUint16 checksum); + + /*! + * \brief checksum + * \return + */ + atUint16 checksum() const; + private: - std::vector m_roomFlags; - std::vector m_overworldEvents; - ALTTPInventory m_inventory; - atUint16 m_rupeeMax; - atUint16 m_rupeeCurrent; - ALTTPDungeonItemFlags m_compasses; - ALTTPDungeonItemFlags m_bigKeys; - ALTTPDungeonItemFlags m_dungeonMaps; - atUint16 m_wishingPond; - atUint8 m_healthMax; - atUint8 m_health; - atUint8 m_magicPower; - atUint8 m_keys; - atUint8 m_bombUpgrades; - atUint8 m_arrowUpgrades; - atUint8 m_heartFiller; - atUint8 m_magicFiller; - ALTTPPendants m_pendants; - atUint8 m_bombFiller; - atUint8 m_arrowFiller; - atUint8 m_arrows; - ALTTPAbilities m_abilityFlags; - ALTTPCrystals m_crystals; - ALTTPMagicUsage m_magicUsage; - std::vector m_dungeonKeys; - ALTTPProgressIndicator m_progressIndicator; - ALTTPProgressFlags1 m_progressFlags1; - ALTTPMapIcon m_mapIcon; - ALTTPStartLocation m_startLocation; - ALTTPProgressFlags2 m_progressFlags2; - ALTTPLightDarkWorldIndicator m_lightDarkWorldIndicator; - ALTTPTagAlong m_tagAlong; - std::vector m_oldManFlags; - atUint8 m_bombFlag; - std::vector m_unknown1; - std::vector m_playerName; - bool m_valid; - std::vector m_dungeonDeathTotals; - atUint16 m_unknown2; - atUint16 m_deathSaveCount; - atInt16 m_postGameDeathCounter; - atUint16 m_checksum; + std::vector m_roomFlags; + std::vector m_overworldEvents; + ALTTPInventory m_inventory; + atUint16 m_rupeeMax; + atUint16 m_rupeeCurrent; + ALTTPDungeonItemFlags m_compasses; + ALTTPDungeonItemFlags m_bigKeys; + ALTTPDungeonItemFlags m_dungeonMaps; + atUint16 m_wishingPond; + atUint8 m_healthMax; + atUint8 m_health; + atUint8 m_magicPower; + atUint8 m_keys; + atUint8 m_bombUpgrades; + atUint8 m_arrowUpgrades; + atUint8 m_heartFiller; + atUint8 m_magicFiller; + ALTTPPendants m_pendants; + atUint8 m_bombFiller; + atUint8 m_arrowFiller; + atUint8 m_arrows; + ALTTPAbilities m_abilityFlags; + ALTTPCrystals m_crystals; + ALTTPMagicUsage m_magicUsage; + std::vector m_dungeonKeys; + ALTTPProgressIndicator m_progressIndicator; + ALTTPProgressFlags1 m_progressFlags1; + ALTTPMapIcon m_mapIcon; + ALTTPStartLocation m_startLocation; + ALTTPProgressFlags2 m_progressFlags2; + ALTTPLightDarkWorldIndicator m_lightDarkWorldIndicator; + ALTTPTagAlong m_tagAlong; + std::vector m_oldManFlags; + atUint8 m_bombFlag; + std::vector m_unknown1; + std::vector m_playerName; + bool m_valid; + std::vector m_dungeonDeathTotals; + atUint16 m_unknown2; + atUint16 m_deathSaveCount; + atInt16 m_postGameDeathCounter; + atUint16 m_checksum; }; -} // zelda - +} // namespace athena diff --git a/include/athena/ALTTPStructs.hpp b/include/athena/ALTTPStructs.hpp index d07a6fc..400dfe2 100644 --- a/include/athena/ALTTPStructs.hpp +++ b/include/athena/ALTTPStructs.hpp @@ -3,196 +3,176 @@ #include #include "athena/Types.hpp" -namespace athena -{ +namespace athena { -struct ALTTPRoomFlags -{ - bool Chest1: 1; - bool Chest2: 1; - bool Chest3: 1; - bool Chest4: 1; - bool Quadrant1: 1; - bool Quadrant2: 1; - bool Quadrant3: 1; - bool Quadrant4: 1; - bool Door1: 1; - bool Door2: 1; - bool Door3: 1; - bool Door4: 1; - bool BossBattleWon: 1; - bool Key: 1; - bool KeyOrChest: 1; - bool ChestOrTile: 1; +struct ALTTPRoomFlags { + bool Chest1 : 1; + bool Chest2 : 1; + bool Chest3 : 1; + bool Chest4 : 1; + bool Quadrant1 : 1; + bool Quadrant2 : 1; + bool Quadrant3 : 1; + bool Quadrant4 : 1; + bool Door1 : 1; + bool Door2 : 1; + bool Door3 : 1; + bool Door4 : 1; + bool BossBattleWon : 1; + bool Key : 1; + bool KeyOrChest : 1; + bool ChestOrTile : 1; }; -struct ALTTPOverworldEvent -{ - bool Unused1: 1; - bool HeartPiece: 1; - bool Overlay: 1; - bool Unused2: 1; - bool Unused3: 1; - bool Unused4: 1; - bool Set: 1; - bool Unused5: 1; +struct ALTTPOverworldEvent { + bool Unused1 : 1; + bool HeartPiece : 1; + bool Overlay : 1; + bool Unused2 : 1; + bool Unused3 : 1; + bool Unused4 : 1; + bool Set : 1; + bool Unused5 : 1; }; -struct ALTTPInventory -{ - char Bow; - char Boomerang; - bool Hookshot; - char Bombs; // Bomb count - char Magic; - bool FireRod; - bool IceRod; - bool Bombos; - bool Ether; - bool Quake; - bool Torch; - bool Hammer; - char Flute; - bool BugNet; - bool Book; - bool Bottles; - bool Somaria; - bool Byrna; - bool MagicCape; - char MagicMirror; - char Gloves; - char Boots; - bool Flippers; - bool MoonPearl; - char Unused; //? - char Sword; - char Shield; - char Armor; - char BottleTypes[4]; +struct ALTTPInventory { + char Bow; + char Boomerang; + bool Hookshot; + char Bombs; // Bomb count + char Magic; + bool FireRod; + bool IceRod; + bool Bombos; + bool Ether; + bool Quake; + bool Torch; + bool Hammer; + char Flute; + bool BugNet; + bool Book; + bool Bottles; + bool Somaria; + bool Byrna; + bool MagicCape; + char MagicMirror; + char Gloves; + char Boots; + bool Flippers; + bool MoonPearl; + char Unused; //? + char Sword; + char Shield; + char Armor; + char BottleTypes[4]; }; /*! \struct ALTTPLightDarkWorldIndicator */ -struct ALTTPLightDarkWorldIndicator -{ - bool Unused1: 1; - bool Unused2: 1; - bool Unused3: 1; - bool Unused4: 1; - bool Unused5: 1; - bool Unused6: 1; - bool IsDarkWorld: 1; - bool Unused7: 1; +struct ALTTPLightDarkWorldIndicator { + bool Unused1 : 1; + bool Unused2 : 1; + bool Unused3 : 1; + bool Unused4 : 1; + bool Unused5 : 1; + bool Unused6 : 1; + bool IsDarkWorld : 1; + bool Unused7 : 1; }; - -struct ALTTPDungeonItemFlags -{ - union - { - struct - { - bool Unused1: 1; - bool Unused2: 1; - bool GanonsTower: 1; - bool TurtleRock: 1; - bool GargoylesDomain: 1; - bool TowerOfHera: 1; - bool IcePalace: 1; - bool SkullWoods: 1; - }; - atUint8 flags1; +struct ALTTPDungeonItemFlags { + union { + struct { + bool Unused1 : 1; + bool Unused2 : 1; + bool GanonsTower : 1; + bool TurtleRock : 1; + bool GargoylesDomain : 1; + bool TowerOfHera : 1; + bool IcePalace : 1; + bool SkullWoods : 1; }; + atUint8 flags1; + }; - union - { - struct - { - bool MiseryMire: 1; - bool DarkPalace: 1; - bool SwampPalace: 1; - bool HyruleCastle2: 1; // unused in orignal game - bool DesertPalace: 1; - bool EasternPalace: 1; - bool HyruleCastle: 1; // unused exist in original game - bool SewerPassage: 1; // unused exist in original game - }; - atUint8 flags2; + union { + struct { + bool MiseryMire : 1; + bool DarkPalace : 1; + bool SwampPalace : 1; + bool HyruleCastle2 : 1; // unused in orignal game + bool DesertPalace : 1; + bool EasternPalace : 1; + bool HyruleCastle : 1; // unused exist in original game + bool SewerPassage : 1; // unused exist in original game }; + atUint8 flags2; + }; }; -struct ALTTPPendants -{ - bool Courage: 1; - bool Wisdom: 1; - bool Power: 1; - bool Unused1: 1; - bool Unused2: 1; - bool Unused3: 1; - bool Unused4: 1; - bool Unused5: 1; +struct ALTTPPendants { + bool Courage : 1; + bool Wisdom : 1; + bool Power : 1; + bool Unused1 : 1; + bool Unused2 : 1; + bool Unused3 : 1; + bool Unused4 : 1; + bool Unused5 : 1; }; -struct ALTTPAbilities -{ - bool Nothing: 1; //? - bool Swim: 1; - bool Dash: 1; - bool Pull: 1; - bool Unknown1: 1; //--- - bool Talk: 1; - bool Read: 1; - bool Unknown2: 1; //--- +struct ALTTPAbilities { + bool Nothing : 1; //? + bool Swim : 1; + bool Dash : 1; + bool Pull : 1; + bool Unknown1 : 1; //--- + bool Talk : 1; + bool Read : 1; + bool Unknown2 : 1; //--- }; -struct ALTTPCrystals -{ - bool MiseryMire: 1; - bool DarkPalace: 1; - bool IcePalace: 1; - bool TurtleRock: 1; - bool SwampPalace: 1; - bool GargoyleDomain: 1; - bool SkullWoods: 1; +struct ALTTPCrystals { + bool MiseryMire : 1; + bool DarkPalace : 1; + bool IcePalace : 1; + bool TurtleRock : 1; + bool SwampPalace : 1; + bool GargoyleDomain : 1; + bool SkullWoods : 1; }; -struct ALTTPMagicUsage -{ - bool Normal: 1; - bool Half: 1; - bool Quarter: 1; - bool Unused1: 1; - bool Unused2: 1; - bool Unused3: 1; - bool Unused4: 1; - bool Unused5: 1; +struct ALTTPMagicUsage { + bool Normal : 1; + bool Half : 1; + bool Quarter : 1; + bool Unused1 : 1; + bool Unused2 : 1; + bool Unused3 : 1; + bool Unused4 : 1; + bool Unused5 : 1; }; - -struct ALTTPProgressFlags1 -{ - bool UncleSecretPassage: 1; - bool DyingPriest: 1; //? - bool ZeldaSanctuary: 1; //? - bool Unused1: 1; - bool UncleLeftHouse: 1; - bool BookOfMudora: 1; //? Math says it's a guess need to investigate - bool DwarfPartner: 1; //? - bool Unused2: 1; +struct ALTTPProgressFlags1 { + bool UncleSecretPassage : 1; + bool DyingPriest : 1; //? + bool ZeldaSanctuary : 1; //? + bool Unused1 : 1; + bool UncleLeftHouse : 1; + bool BookOfMudora : 1; //? Math says it's a guess need to investigate + bool DwarfPartner : 1; //? + bool Unused2 : 1; }; - -struct ALTTPProgressFlags2 -{ - bool BottleFromBum: 1; - bool BottleFromSalesMen: 1; - bool Unused1: 1; //? - bool FluteBoy: 1; - bool ThiefsChest: 1; - bool SavedSmithPartner: 1; - bool Unused2: 1; //? - bool SmithsHaveSword: 1; +struct ALTTPProgressFlags2 { + bool BottleFromBum : 1; + bool BottleFromSalesMen : 1; + bool Unused1 : 1; //? + bool FluteBoy : 1; + bool ThiefsChest : 1; + bool SavedSmithPartner : 1; + bool Unused2 : 1; //? + bool SmithsHaveSword : 1; }; -} - +} // namespace athena diff --git a/include/athena/Checksums.hpp b/include/athena/Checksums.hpp index 871c45c..68402b1 100644 --- a/include/athena/Checksums.hpp +++ b/include/athena/Checksums.hpp @@ -2,10 +2,10 @@ #include "athena/Global.hpp" -namespace athena::checksums -{ -atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed = 0xFFFFFFFFFFFFFFFF, atUint64 final = 0xFFFFFFFFFFFFFFFF); +namespace athena::checksums { +atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed = 0xFFFFFFFFFFFFFFFF, + atUint64 final = 0xFFFFFFFFFFFFFFFF); atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed = 0xFFFFFFFF, atUint32 final = 0xFFFFFFFF); atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed = 0xFFFF, atUint16 final = 0); atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed = 0, atUint16 final = 0); -} +} // namespace athena::checksums diff --git a/include/athena/ChecksumsLiterals.hpp b/include/athena/ChecksumsLiterals.hpp index 0d980f3..1f77c56 100644 --- a/include/athena/ChecksumsLiterals.hpp +++ b/include/athena/ChecksumsLiterals.hpp @@ -2,196 +2,161 @@ #include -namespace athena::checksums::literals -{ +namespace athena::checksums::literals { -constexpr uint32_t crc32_table[] = -{ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +constexpr uint32_t crc32_table[] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}; + +template +struct Crc32Impl {}; + +template +struct Crc32Impl { + static constexpr uint32_t value = + Crc32Impl(CRC) ^ static_cast(Head)] ^ (CRC >> 8), + Tail...>::value; }; -template struct Crc32Impl { +template +struct Crc32Impl { + static constexpr uint32_t value = CRC ^ 0xFFFFFFFF; }; -template struct Crc32Impl { - static constexpr uint32_t value = Crc32Impl< - crc32_table[static_cast(CRC) ^ static_cast(Head)] - ^ (CRC >> 8), Tail...>::value; -}; +template +using Crc32 = Crc32Impl<0xFFFFFFFF, Chars...>; -template struct Crc32Impl { - static constexpr uint32_t value = CRC ^ 0xFFFFFFFF; -}; - - -template using Crc32 = Crc32Impl<0xFFFFFFFF, Chars...>; - -constexpr uint32_t crc32_rec(uint32_t crc, const char *s) { - return *s == 0 ? crc ^ 0xFFFFFFFF : - crc32_rec(crc32_table[static_cast(crc) ^ - static_cast(*s)] - ^ (crc >> 8), s + 1); +constexpr uint32_t crc32_rec(uint32_t crc, const char* s) { + return *s == 0 ? crc ^ 0xFFFFFFFF + : crc32_rec(crc32_table[static_cast(crc) ^ static_cast(*s)] ^ (crc >> 8), + s + 1); } -constexpr uint32_t operator "" _crc32(const char *s, size_t len) { - return crc32_rec(0xFFFFFFFF, s); +constexpr uint32_t operator"" _crc32(const char* s, size_t len) { return crc32_rec(0xFFFFFFFF, s); } + +static_assert("Hello"_crc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, "CRC32 values don't match"); +static_assert("0"_crc32 == Crc32<'0'>::value, "CRC32 values don't match"); + +constexpr uint32_t rcrc32_rec(uint32_t crc, const char* s) { + return *s == 0 ? crc + : crc32_rec(crc32_table[static_cast(crc) ^ static_cast(*s)] ^ (crc >> 8), + s + 1); } -static_assert("Hello"_crc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, - "CRC32 values don't match"); -static_assert("0"_crc32 == Crc32<'0'>::value, - "CRC32 values don't match"); +constexpr uint32_t operator"" _rcrc32(const char* s, size_t len) { return rcrc32_rec(0xFFFFFFFF, s); } +static_assert("Hello"_rcrc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, "CRC32 values don't match"); +static_assert("0"_rcrc32 == Crc32<'0'>::value, "CRC32 values don't match"); -constexpr uint32_t rcrc32_rec(uint32_t crc, const char *s) { - return *s == 0 ? crc : - crc32_rec(crc32_table[static_cast(crc) ^ - static_cast(*s)] - ^ (crc >> 8), s + 1); -} +constexpr uint64_t crc64_table[] = { + 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x493366450E42ECDF, + 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, + 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, + 0x1C4488F3E8F96ED4, 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, + 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, 0xF45BB4758C645C51, + 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, 0xBD68D2308226B08E, 0xFF9833DB2BCC861D, + 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, + 0x0B6BD3C3DBFD506B, 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, + 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x172F5B3033043EBF, + 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, + 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, + 0x2465CD79455E395B, 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A, + 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, 0xDA050215EA6C212F, + 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, + 0x16D7A787B7FAA0D6, 0x5427466C1E109645, 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, + 0x8F72ECA30CD7A324, 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, + 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, 0xF50B1CAF74CF481F, + 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, + 0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, + 0xA07CF2199274CA14, 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, + 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x84193F60D72AF34F, + 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, + 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, + 0xB753A929A170F4AB, 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874, + 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, 0xAB1721DA49899A7F, + 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, + 0x731B26172EE619EB, 0x31EBC7FC870C2F78, 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, + 0x78D8A1B9894EC3A7, 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, + 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, 0x90C79D3FEDD3F122, + 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, + 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, + 0xC5B073890B687329, 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, + 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0x73B3727A52B393CC, + 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, + 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, + 0x26C49CCCB40811C7, 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149, + 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, 0xCEDBA04AD0952342, + 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, + 0x020905D88D03A2BB, 0x40F9E43324E99428, 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, + 0xEBEEC5E96D600E57, 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, + 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, 0xF7AA4D1A85996083, + 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, + 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, + 0xC4E0DB53F3C36767, 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206, + 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, 0xE085162AB69D5E3C, + 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, 0xA9B6706FB8DFB2E3, 0xEB46918411358470, + 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, + 0xB5F2F89C5026DC37, 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8, + 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, 0xCF8B0890283E370C, + 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, 0x14DEA25F3AF9026D, 0x562E43B4931334FE, + 0x913F6188692D6F4B, 0xD3CF8063C0C759D8, 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, + 0x9AFCE626CE85B507}; -constexpr uint32_t operator "" _rcrc32(const char *s, size_t len) { - return rcrc32_rec(0xFFFFFFFF, s); -} +template +struct Crc64Impl {}; -static_assert("Hello"_rcrc32 == Crc32<'H', 'e', 'l', 'l', 'o'>::value, - "CRC32 values don't match"); -static_assert("0"_rcrc32 == Crc32<'0'>::value, - "CRC32 values don't match"); - - - -constexpr uint64_t crc64_table[] = -{ - 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, - 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, - 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, - 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4, - 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, - 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, - 0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, - 0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, - 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B, - 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, - 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, - 0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, - 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, - 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B, - 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A, - 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, - 0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, - 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645, - 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324, - 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, - 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, - 0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, - 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB, - 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14, - 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, - 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, - 0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, - 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, - 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB, - 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874, - 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, - 0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, - 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78, - 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7, - 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, - 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, - 0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, - 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, - 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329, - 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, - 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, - 0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, - 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, - 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7, - 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149, - 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, - 0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, - 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428, - 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57, - 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, - 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, - 0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, - 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, - 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767, - 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206, - 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, - 0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, - 0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, - 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37, - 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8, - 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, - 0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, - 0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8, - 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507 +template +struct Crc64Impl { + static constexpr uint64_t value = + Crc64Impl(CRC >> 56) ^ static_cast(Head)] ^ (CRC << 8), + Tail...>::value; }; -template struct Crc64Impl { +template +struct Crc64Impl { + static constexpr uint64_t value = CRC ^ 0xFFFFFFFFFFFFFFFF; }; -template struct Crc64Impl { - static constexpr uint64_t value = Crc64Impl< - crc64_table[static_cast(CRC >> 56) ^ static_cast(Head)] - ^ (CRC << 8), Tail...>::value; -}; +template +using Crc64 = Crc64Impl<0xFFFFFFFFFFFFFFFF, Chars...>; -template struct Crc64Impl { - static constexpr uint64_t value = CRC ^ 0xFFFFFFFFFFFFFFFF; -}; - - -template using Crc64 = Crc64Impl<0xFFFFFFFFFFFFFFFF, Chars...>; - -constexpr uint64_t crc64_rec(uint64_t crc, const char *s) { - return *s == 0 ? crc ^ 0xFFFFFFFFFFFFFFFF : - crc64_rec(crc64_table[static_cast(crc >> 56) ^ - static_cast(*s)] - ^ (crc << 8), s + 1); +constexpr uint64_t crc64_rec(uint64_t crc, const char* s) { + return *s == 0 ? crc ^ 0xFFFFFFFFFFFFFFFF + : crc64_rec(crc64_table[static_cast(crc >> 56) ^ static_cast(*s)] ^ + (crc << 8), + s + 1); } -constexpr uint64_t operator "" _crc64(const char *s, size_t len) { - return crc64_rec(0xFFFFFFFFFFFFFFFF, s); -} - -static_assert("Hello"_crc64 == Crc64<'H', 'e', 'l', 'l', 'o'>::value, - "CRC64 values don't match"); -static_assert("0"_crc64 == Crc64<'0'>::value, - "CRC64 values don't match"); - -} +constexpr uint64_t operator"" _crc64(const char* s, size_t len) { return crc64_rec(0xFFFFFFFFFFFFFFFF, s); } +static_assert("Hello"_crc64 == Crc64<'H', 'e', 'l', 'l', 'o'>::value, "CRC64 values don't match"); +static_assert("0"_crc64 == Crc64<'0'>::value, "CRC64 values don't match"); +} // namespace athena::checksums::literals diff --git a/include/athena/Compression.hpp b/include/athena/Compression.hpp index 91cd47e..4793d02 100644 --- a/include/athena/Compression.hpp +++ b/include/athena/Compression.hpp @@ -2,8 +2,7 @@ #include "athena/Global.hpp" -namespace athena::io::Compression -{ +namespace athena::io::Compression { // Zlib compression atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen); atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen); @@ -17,4 +16,4 @@ atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data); atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst); atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended = false); -} +} // namespace athena::io::Compression diff --git a/include/athena/DNA.hpp b/include/athena/DNA.hpp index e22c397..3fe92a2 100644 --- a/include/athena/DNA.hpp +++ b/include/athena/DNA.hpp @@ -13,8 +13,7 @@ #include #include -namespace athena::io -{ +namespace athena::io { /** * @brief Base DNA class used against 'atdna' @@ -26,81 +25,80 @@ namespace athena::io * a streamed medium */ template -struct DNA -{ - /** - * @brief Designated byte-order used for serializing fields - */ - static constexpr Endian DNAEndian = DNAE; +struct DNA { + /** + * @brief Designated byte-order used for serializing fields + */ + static constexpr Endian DNAEndian = DNAE; - /** - * @brief Template type signaling atdna to capture the value where it's used - * @tparam T The type of the value. Can be any numeric type or atVec* type - * @tparam VE Endianness of the value - */ - template - using Value = T; + /** + * @brief Template type signaling atdna to capture the value where it's used + * @tparam T The type of the value. Can be any numeric type or atVec* type + * @tparam VE Endianness of the value + */ + template + using Value = T; - /** - * @brief Template type wrapping std::vector and signaling atdna to manipulate it where it's used - * @tparam T The type of contained elements. Can be any numeric type, atVec* type, or another DNA subclass - * @tparam cntVar C++ expression wrapped in DNA_COUNT macro to determine number of elements for vector - * @tparam VE Endianness of the contained values - */ - template - using Vector = std::vector; + /** + * @brief Template type wrapping std::vector and signaling atdna to manipulate it where it's used + * @tparam T The type of contained elements. Can be any numeric type, atVec* type, or another DNA subclass + * @tparam cntVar C++ expression wrapped in DNA_COUNT macro to determine number of elements for vector + * @tparam VE Endianness of the contained values + */ + template + using Vector = std::vector; - /** - * @brief Template type wrapping std::unique_ptr and signaling atdna to read a - * raw byte-buffer where it's used - * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of bytes for buffer - */ - template - using Buffer = std::unique_ptr; + /** + * @brief Template type wrapping std::unique_ptr and signaling atdna to read a + * raw byte-buffer where it's used + * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of bytes for buffer + */ + template + using Buffer = std::unique_ptr; - /** - * @brief Template type wrapping std::string and signaling atdna to read string data where it's used - * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string - * -1 literal indicates null-terminated string - */ - template - using String = std::string; + /** + * @brief Template type wrapping std::string and signaling atdna to read string data where it's used + * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string + * -1 literal indicates null-terminated string + */ + template + using String = std::string; - /** - * @brief Template type wrapping std::wstring and signaling atdna to read wstring data where it's used - * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for wstring - * -1 literal indicates null-terminated wstring - */ - template - using WString = std::wstring; + /** + * @brief Template type wrapping std::wstring and signaling atdna to read wstring data where it's used + * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for wstring + * -1 literal indicates null-terminated wstring + */ + template + using WString = std::wstring; - /** - * @brief Meta Template signaling atdna to insert a stream seek where it's used - * @tparam offset C++ expression wrapped in DNA_COUNT macro to determine number of bytes to seek - * @tparam direction SeekOrigin to seek relative to - */ - template - struct Seek {}; + /** + * @brief Meta Template signaling atdna to insert a stream seek where it's used + * @tparam offset C++ expression wrapped in DNA_COUNT macro to determine number of bytes to seek + * @tparam direction SeekOrigin to seek relative to + */ + template + struct Seek {}; - /** - * @brief Meta Template signaling atdna to insert an aligning stream seek where it's used - * @tparam align Number of bytes to align to - */ - template - struct Align {}; + /** + * @brief Meta Template signaling atdna to insert an aligning stream seek where it's used + * @tparam align Number of bytes to align to + */ + template + struct Align {}; - /** - * @brief Meta Template preventing atdna from emitting read/write implementations - */ - struct Delete {}; + /** + * @brief Meta Template preventing atdna from emitting read/write implementations + */ + struct Delete {}; - /* Bring fundamental operations into DNA subclasses for easier per-op overrides */ - using Read = athena::io::Read; - using Write = athena::io::Write; - using BinarySize = athena::io::BinarySize; - using PropCount = athena::io::PropCount; - using ReadYaml = athena::io::ReadYaml; - using WriteYaml = athena::io::WriteYaml; + /* Bring fundamental operations into DNA subclasses for easier per-op overrides */ + using Read = athena::io::Read; + using Write = athena::io::Write; + using BinarySize = athena::io::BinarySize; + using PropCount = athena::io::PropCount; + using ReadYaml = athena::io::ReadYaml; + using WriteYaml = athena::io::WriteYaml; }; /** @@ -120,24 +118,22 @@ struct DNA * { (Do stuff with `r`) } */ template -struct DNAV : DNA -{ - virtual ~DNAV() = default; - virtual void read(athena::io::IStreamReader& r) = 0; - virtual void write(athena::io::IStreamWriter& w) const = 0; - virtual void binarySize(size_t& s) const = 0; - virtual const char* DNATypeV() const = 0; +struct DNAV : DNA { + virtual ~DNAV() = default; + virtual void read(athena::io::IStreamReader& r) = 0; + virtual void write(athena::io::IStreamWriter& w) const = 0; + virtual void binarySize(size_t& s) const = 0; + virtual const char* DNATypeV() const = 0; }; template -struct DNAVYaml : DNAV -{ - virtual ~DNAVYaml() = default; - virtual void read(athena::io::IStreamReader& r) = 0; - virtual void write(athena::io::IStreamWriter& w) const = 0; - virtual void binarySize(size_t& s) const = 0; - virtual void read(athena::io::YAMLDocReader& r) = 0; - virtual void write(athena::io::YAMLDocWriter& w) const = 0; +struct DNAVYaml : DNAV { + virtual ~DNAVYaml() = default; + virtual void read(athena::io::IStreamReader& r) = 0; + virtual void write(athena::io::IStreamWriter& w) const = 0; + virtual void binarySize(size_t& s) const = 0; + virtual void read(athena::io::YAMLDocReader& r) = 0; + virtual void write(athena::io::YAMLDocWriter& w) const = 0; }; /** Macro to supply count variable to atdna and mute it for other compilers */ @@ -147,6 +143,4 @@ struct DNAVYaml : DNAV #define AT_DNA_COUNT(cnt) 0 #endif -} - - +} // namespace athena::io diff --git a/include/athena/DNAOp.hpp b/include/athena/DNAOp.hpp index fe159f2..4a6b111 100644 --- a/include/athena/DNAOp.hpp +++ b/include/athena/DNAOp.hpp @@ -7,241 +7,204 @@ #include "ChecksumsLiterals.hpp" #include -namespace athena::io -{ +namespace athena::io { -struct PropId -{ - const char* name = nullptr; - uint32_t rcrc32 = 0xffffffff; - uint64_t crc64 = 0x0; - template constexpr T opget() const; - constexpr PropId() = default; - constexpr PropId(const char* name, uint32_t rcrc32, uint64_t crc64) - : name(name), rcrc32(rcrc32), crc64(crc64) {} - constexpr PropId(const char* name) - : name(name), - rcrc32(athena::checksums::literals::rcrc32_rec(0xFFFFFFFF, name)), - crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name)) {} - constexpr PropId(const char* name, uint32_t rcrc32) - : name(name), - rcrc32(rcrc32), - crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name)) {} +struct PropId { + const char* name = nullptr; + uint32_t rcrc32 = 0xffffffff; + uint64_t crc64 = 0x0; + template + constexpr T opget() const; + constexpr PropId() = default; + constexpr PropId(const char* name, uint32_t rcrc32, uint64_t crc64) : name(name), rcrc32(rcrc32), crc64(crc64) {} + constexpr PropId(const char* name) + : name(name) + , rcrc32(athena::checksums::literals::rcrc32_rec(0xFFFFFFFF, name)) + , crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name)) {} + constexpr PropId(const char* name, uint32_t rcrc32) + : name(name), rcrc32(rcrc32), crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name)) {} }; template <> -constexpr uint32_t PropId::opget() const { return rcrc32; } +constexpr uint32_t PropId::opget() const { + return rcrc32; +} template <> -constexpr uint64_t PropId::opget() const { return crc64; } +constexpr uint64_t PropId::opget() const { + return crc64; +} -namespace literals -{ -constexpr PropId operator "" _propid(const char* s, size_t len) -{ - return {s}; -} -} +namespace literals { +constexpr PropId operator"" _propid(const char* s, size_t len) { return {s}; } +} // namespace literals #define AT_PROP_CASE(...) case athena::io::PropId(__VA_ARGS__).opget() #if defined(__atdna__) -# define AT_OVERRIDE_RCRC32(rcrc32) __attribute__((annotate("rcrc32=" #rcrc32))) +#define AT_OVERRIDE_RCRC32(rcrc32) __attribute__((annotate("rcrc32=" #rcrc32))) #else -# define AT_OVERRIDE_RCRC32(rcrc32) +#define AT_OVERRIDE_RCRC32(rcrc32) #endif #if defined(__atdna__) -# define AT_SPECIALIZE_PARMS(...) __attribute__((annotate("specparms=" #__VA_ARGS__))) +#define AT_SPECIALIZE_PARMS(...) __attribute__((annotate("specparms=" #__VA_ARGS__))) #else -# define AT_SPECIALIZE_PARMS(...) +#define AT_SPECIALIZE_PARMS(...) #endif -enum class PropType -{ - None, - CRC32, - CRC64 -}; +enum class PropType { None, CRC32, CRC64 }; template -using __IsPODType = typename std::disjunction>, - std::is_convertible&, atVec2f&>, - std::is_convertible&, atVec3f&>, - std::is_convertible&, atVec4f&>, - std::is_convertible&, atVec2d&>, - std::is_convertible&, atVec3d&>, - std::is_convertible&, atVec4d&>>; +using __IsPODType = typename std::disjunction< + std::is_arithmetic>, std::is_convertible&, atVec2f&>, + std::is_convertible&, atVec3f&>, std::is_convertible&, atVec4f&>, + std::is_convertible&, atVec2d&>, std::is_convertible&, atVec3d&>, + std::is_convertible&, atVec4d&>>; template inline constexpr bool __IsPODType_v = __IsPODType::value; template -using __CastPODType = typename std::conditional_t&, atVec2f&>, atVec2f, - std::conditional_t&, atVec3f&>, atVec3f, - std::conditional_t&, atVec4f&>, atVec4f, - std::conditional_t&, atVec2d&>, atVec2d, - std::conditional_t&, atVec3d&>, atVec3d, - std::conditional_t&, atVec4d&>, atVec4d, - std::remove_cv_t>>>>>>; +using __CastPODType = typename std::conditional_t< + std::is_convertible_v&, atVec2f&>, atVec2f, + std::conditional_t< + std::is_convertible_v&, atVec3f&>, atVec3f, + std::conditional_t< + std::is_convertible_v&, atVec4f&>, atVec4f, + std::conditional_t< + std::is_convertible_v&, atVec2d&>, atVec2d, + std::conditional_t&, atVec3d&>, atVec3d, + std::conditional_t&, atVec4d&>, atVec4d, + std::remove_cv_t>>>>>>; template -static inline uint16_t __Read16(IStreamReader& r) -{ - return DNAE == Endian::Big ? r.readUint16Big() : r.readUint16Little(); +static inline uint16_t __Read16(IStreamReader& r) { + return DNAE == Endian::Big ? r.readUint16Big() : r.readUint16Little(); } template -static inline void __Write16(IStreamWriter& w, uint16_t v) -{ - DNAE == Endian::Big ? w.writeUint16Big(v) : w.writeUint16Little(v); +static inline void __Write16(IStreamWriter& w, uint16_t v) { + DNAE == Endian::Big ? w.writeUint16Big(v) : w.writeUint16Little(v); } template -static inline uint32_t __Read32(IStreamReader& r) -{ - return DNAE == Endian::Big ? r.readUint32Big() : r.readUint32Little(); +static inline uint32_t __Read32(IStreamReader& r) { + return DNAE == Endian::Big ? r.readUint32Big() : r.readUint32Little(); } template -static inline void __Write32(IStreamWriter& w, uint32_t v) -{ - DNAE == Endian::Big ? w.writeUint32Big(v) : w.writeUint32Little(v); +static inline void __Write32(IStreamWriter& w, uint32_t v) { + DNAE == Endian::Big ? w.writeUint32Big(v) : w.writeUint32Little(v); } template -static inline uint64_t __Read64(IStreamReader& r) -{ - return DNAE == Endian::Big ? r.readUint64Big() : r.readUint64Little(); +static inline uint64_t __Read64(IStreamReader& r) { + return DNAE == Endian::Big ? r.readUint64Big() : r.readUint64Little(); } template -static inline void __Write64(IStreamWriter& w, uint64_t v) -{ - DNAE == Endian::Big ? w.writeUint64Big(v) : w.writeUint64Little(v); +static inline void __Write64(IStreamWriter& w, uint64_t v) { + DNAE == Endian::Big ? w.writeUint64Big(v) : w.writeUint64Little(v); } template -struct BinarySize -{ - using PropT = std::conditional_t; - using StreamT = size_t; - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& s) - { - if (PropOp != PropType::None) - { - /* Accessed via Enumerate, header */ - s += 6; - } - using PODType = std::underlying_type_t; - BinarySize::Do(id, *reinterpret_cast(&var), s); +struct BinarySize { + using PropT = std::conditional_t; + using StreamT = size_t; + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { + if (PropOp != PropType::None) { + /* Accessed via Enumerate, header */ + s += 6; } - template - static typename std::enable_if_t<__IsPODType_v> - Do(const PropId& id, T& var, StreamT& s) - { - if (PropOp != PropType::None) - { - /* Accessed via Enumerate, header */ - s += 6; - } - using CastT = __CastPODType; - BinarySize::Do(id, static_cast(const_cast&>(var)), s); + using PODType = std::underlying_type_t; + BinarySize::Do(id, *reinterpret_cast(&var), s); + } + template + static typename std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& s) { + if (PropOp != PropType::None) { + /* Accessed via Enumerate, header */ + s += 6; } - template - static typename std::enable_if_t<__IsDNARecord_v && PropOp != PropType::None> - Do(const PropId& id, T& var, StreamT& s) - { - /* Accessed via Enumerate, header */ - s += 6; - var.template Enumerate>(s); - } - template - static typename std::enable_if_t<__IsDNARecord_v && PropOp == PropType::None> - Do(const PropId& id, T& var, StreamT& s) - { - var.template Enumerate>(s); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& s) - { - for (auto& v : var) - BinarySize::Do, DNAE>(id, v, s); - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) - { - BinarySize::Do(id, var, s); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& s) - { - for (T& v : vector) - BinarySize::Do(id, v, s); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& s) - { - /* libc++ specializes vector as a bitstream */ - s += vector.size(); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& s) - { - if (buf) - s += count; - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& s) - { - s += str.size() + 1; - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) - { - if (count < 0) - s += str.size() + 1; - else - s += count; - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& s) - { - s += str.size() * 2 + 2; - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) - { - if (count < 0) - s += str.size() * 2 + 2; - else - s += count * 2; - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) - { - switch (whence) - { - case SeekOrigin::Begin: - s = amount; - break; - case SeekOrigin::Current: - s += amount; - break; - default: - break; - } - } - static void DoAlign(atInt64 amount, StreamT& s) - { - s = (s + amount-1) / amount * amount; + using CastT = __CastPODType; + BinarySize::Do(id, static_cast(const_cast&>(var)), s); + } + template + static typename std::enable_if_t<__IsDNARecord_v && PropOp != PropType::None> Do(const PropId& id, T& var, + StreamT& s) { + /* Accessed via Enumerate, header */ + s += 6; + var.template Enumerate>(s); + } + template + static typename std::enable_if_t<__IsDNARecord_v && PropOp == PropType::None> Do(const PropId& id, T& var, + StreamT& s) { + var.template Enumerate>(s); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { + for (auto& v : var) + BinarySize::Do, DNAE>(id, v, s); + } + template + static void DoSize(const PropId& id, T& var, StreamT& s) { + BinarySize::Do(id, var, s); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, + const S& count, StreamT& s) { + for (T& v : vector) + BinarySize::Do(id, v, s); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, + StreamT& s) { + /* libc++ specializes vector as a bitstream */ + s += vector.size(); + } + static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& s) { + if (buf) + s += count; + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { + s += str.size() + 1; + } + static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) { + if (count < 0) + s += str.size() + 1; + else + s += count; + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { + s += str.size() * 2 + 2; + } + template + static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) { + if (count < 0) + s += str.size() * 2 + 2; + else + s += count * 2; + } + static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) { + switch (whence) { + case SeekOrigin::Begin: + s = amount; + break; + case SeekOrigin::Current: + s += amount; + break; + default: + break; } + } + static void DoAlign(atInt64 amount, StreamT& s) { s = (s + amount - 1) / amount * amount; } }; -#define __BINARY_SIZE_S(type, endian) template <> template <> inline void BinarySize::Do \ - (const PropId& id, type& var, BinarySize::StreamT& s) +#define __BINARY_SIZE_S(type, endian) \ + template <> \ + template <> \ + inline void BinarySize::Do(const PropId& id, type& var, BinarySize::StreamT& s) __BINARY_SIZE_S(bool, Endian::Big) { s += 1; } __BINARY_SIZE_S(atInt8, Endian::Big) { s += 1; } __BINARY_SIZE_S(atUint8, Endian::Big) { s += 1; } @@ -278,182 +241,150 @@ __BINARY_SIZE_S(atVec4f, Endian::Little) { s += 16; } __BINARY_SIZE_S(atVec4d, Endian::Little) { s += 32; } template -struct PropCount -{ - using PropT = std::conditional_t; - using StreamT = size_t; - template - static void Do(const PropId& id, T& var, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) - { - PropCount::Do(id, var, s); - } - template - static void Do(const PropId& id, std::vector& vector, const S& count, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) - { - /* Only reports one level of properties */ - s += 1; - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) {} - static void DoAlign(atInt64 amount, StreamT& s) {} +struct PropCount { + using PropT = std::conditional_t; + using StreamT = size_t; + template + static void Do(const PropId& id, T& var, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + template + static void DoSize(const PropId& id, T& var, StreamT& s) { + PropCount::Do(id, var, s); + } + template + static void Do(const PropId& id, std::vector& vector, const S& count, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + template + static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) { + /* Only reports one level of properties */ + s += 1; + } + static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) {} + static void DoAlign(atInt64 amount, StreamT& s) {} }; template -struct Read -{ - using PropT = std::conditional_t; - using StreamT = IStreamReader; - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& r) - { - using PODType = std::underlying_type_t; - Read::Do(id, *reinterpret_cast(&var), r); +struct Read { + using PropT = std::conditional_t; + using StreamT = IStreamReader; + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& r) { + using PODType = std::underlying_type_t; + Read::Do(id, *reinterpret_cast(&var), r); + } + template + static typename std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& r) { + using CastT = __CastPODType; + Read::Do(id, static_cast(var), r); + } + template + static typename std::enable_if_t<__IsDNARecord() && PropOp == PropType::None> Do(const PropId& id, T& var, + StreamT& r) { + var.template Enumerate>(r); + } + template + static typename std::enable_if_t<__IsDNARecord() && PropOp != PropType::None> Do(const PropId& id, T& var, + StreamT& r) { + /* Accessed via Lookup, no header */ + atUint16 propCount = __Read16(r); + for (atUint32 i = 0; i < propCount; ++i) { + atUint64 hash; + if (PropOp == PropType::CRC64) + hash = __Read64(r); + else + hash = __Read32(r); + atInt64 size = __Read16(r); + atInt64 start = r.position(); + var.template Lookup>(hash, r); + atInt64 actualRead = r.position() - start; + if (actualRead != size) + r.seek(size - actualRead); } - template - static typename std::enable_if_t<__IsPODType_v> - Do(const PropId& id, T& var, StreamT& r) - { - using CastT = __CastPODType; - Read::Do(id, static_cast(var), r); - } - template - static typename std::enable_if_t<__IsDNARecord() && PropOp == PropType::None> - Do(const PropId& id, T& var, StreamT& r) - { - var.template Enumerate>(r); - } - template - static typename std::enable_if_t<__IsDNARecord() && PropOp != PropType::None> - Do(const PropId& id, T& var, StreamT& r) - { - /* Accessed via Lookup, no header */ - atUint16 propCount = __Read16(r); - for (atUint32 i = 0; i < propCount; ++i) - { - atUint64 hash; - if (PropOp == PropType::CRC64) - hash = __Read64(r); - else - hash = __Read32(r); - atInt64 size = __Read16(r); - atInt64 start = r.position(); - var.template Lookup>(hash, r); - atInt64 actualRead = r.position() - start; - if (actualRead != size) - r.seek(size - actualRead); - } - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& s) - { - for (auto& v : var) - Read::Do, DNAE>(id, v, s); - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) - { - Read::Do(id, var, s); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& r) - { - vector.clear(); - vector.reserve(count); - for (size_t i = 0; i < static_cast(count); ++i) - { - vector.emplace_back(); - Read::Do(id, vector.back(), r); - } - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& r) - { - /* libc++ specializes vector as a bitstream */ - vector.clear(); - vector.reserve(count); - for (size_t i = 0; i < count; ++i) - vector.push_back(r.readBool()); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& r) - { - buf.reset(new atUint8[count]); - r.readUBytesToBuf(buf.get(), count); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& r) - { - str = r.readString(); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) - { - str = r.readString(count); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& r) - { - Read::Do(id, str, r); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) - { - Read::Do(id, str, count, r); - } - 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); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { + for (auto& v : var) + Read::Do, DNAE>(id, v, s); + } + template + static void DoSize(const PropId& id, T& var, StreamT& s) { + Read::Do(id, var, s); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, + const S& count, StreamT& r) { + vector.clear(); + vector.reserve(count); + for (size_t i = 0; i < static_cast(count); ++i) { + vector.emplace_back(); + Read::Do(id, vector.back(), r); } + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, + StreamT& r) { + /* libc++ specializes vector as a bitstream */ + vector.clear(); + vector.reserve(count); + for (size_t i = 0; i < count; ++i) + vector.push_back(r.readBool()); + } + static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& r) { + buf.reset(new atUint8[count]); + r.readUBytesToBuf(buf.get(), count); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { + str = r.readString(); + } + static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) { str = r.readString(count); } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { + Read::Do(id, str, r); + } + template + static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) { + Read::Do(id, str, count, r); + } + 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); + } }; -#define __READ_S(type, endian) template <> template <> inline void Read::Do \ - (const PropId& id, type& var, Read::StreamT& r) -#define __READ_WSTR_S(endian) template <> template <> inline void Read::Do \ - (const PropId& id, std::wstring& str, Read::StreamT& r) -#define __READ_WSTRC_S(endian) template <> template <> inline void Read::Do \ - (const PropId& id, std::wstring& str, atInt32 count, Read::StreamT& r) +#define __READ_S(type, endian) \ + template <> \ + template <> \ + inline void Read::Do(const PropId& id, type& var, Read::StreamT& r) +#define __READ_WSTR_S(endian) \ + template <> \ + template <> \ + inline void Read::Do(const PropId& id, std::wstring& str, Read::StreamT& r) +#define __READ_WSTRC_S(endian) \ + template <> \ + template <> \ + inline void Read::Do(const PropId& id, std::wstring& str, atInt32 count, Read::StreamT& r) __READ_S(bool, Endian::Big) { var = r.readBool(); } __READ_S(atInt8, Endian::Big) { var = r.readByte(); } __READ_S(atUint8, Endian::Big) { var = r.readUByte(); } @@ -494,138 +425,117 @@ __READ_WSTR_S(Endian::Little) { str = r.readWStringLittle(); } __READ_WSTRC_S(Endian::Little) { str = r.readWStringLittle(count); } template -struct Write -{ - using PropT = std::conditional_t; - using StreamT = IStreamWriter; - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& w) - { - if (PropOp != PropType::None) - { - /* Accessed via Enumerate, header */ - if (PropOp == PropType::CRC64) - __Write64(w, id.crc64); - else - __Write32(w, id.rcrc32); - size_t binarySize = 0; - BinarySize::Do(id, var, binarySize); - DNAE == Endian::Big ? w.writeUint16Big(atUint16(binarySize)) : w.writeUint16Little(atUint16(binarySize)); - } - using PODType = std::underlying_type_t; - Write::Do(id, *reinterpret_cast(&var), w); +struct Write { + using PropT = std::conditional_t; + using StreamT = IStreamWriter; + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& w) { + if (PropOp != PropType::None) { + /* Accessed via Enumerate, header */ + if (PropOp == PropType::CRC64) + __Write64(w, id.crc64); + else + __Write32(w, id.rcrc32); + size_t binarySize = 0; + BinarySize::Do(id, var, binarySize); + DNAE == Endian::Big ? w.writeUint16Big(atUint16(binarySize)) : w.writeUint16Little(atUint16(binarySize)); } - template - static typename std::enable_if_t<__IsPODType_v> - Do(const PropId& id, T& var, StreamT& w) - { - using CastT = __CastPODType; - if (PropOp != PropType::None) - { - /* Accessed via Enumerate, header */ - if (PropOp == PropType::CRC64) - __Write64(w, id.crc64); - else - __Write32(w, id.rcrc32); - size_t binarySize = 0; - BinarySize::Do(id, static_cast(const_cast&>(var)), binarySize); - __Write16(w, atUint16(binarySize)); - } - Write::Do(id, static_cast(const_cast&>(var)), w); + using PODType = std::underlying_type_t; + Write::Do(id, *reinterpret_cast(&var), w); + } + template + static typename std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& w) { + using CastT = __CastPODType; + if (PropOp != PropType::None) { + /* Accessed via Enumerate, header */ + if (PropOp == PropType::CRC64) + __Write64(w, id.crc64); + else + __Write32(w, id.rcrc32); + size_t binarySize = 0; + BinarySize::Do(id, static_cast(const_cast&>(var)), + binarySize); + __Write16(w, atUint16(binarySize)); } - template - static typename std::enable_if_t<__IsDNARecord() && PropOp != PropType::None> - Do(const PropId& id, T& var, StreamT& w) - { - /* Accessed via Enumerate, header */ - if (PropOp == PropType::CRC64) - __Write64(w, id.crc64); - else - __Write32(w, id.rcrc32); - size_t binarySize = 0; - var.template Enumerate>(binarySize); - __Write16(w, atUint16(binarySize)); + Write::Do(id, static_cast(const_cast&>(var)), w); + } + template + static typename std::enable_if_t<__IsDNARecord() && PropOp != PropType::None> Do(const PropId& id, T& var, + StreamT& w) { + /* Accessed via Enumerate, header */ + if (PropOp == PropType::CRC64) + __Write64(w, id.crc64); + else + __Write32(w, id.rcrc32); + size_t binarySize = 0; + var.template Enumerate>(binarySize); + __Write16(w, atUint16(binarySize)); - size_t propCount = 0; - var.template Enumerate>(propCount); - __Write16(w, atUint16(propCount)); - var.template Enumerate>(w); - } - template - static typename std::enable_if_t<__IsDNARecord() && PropOp == PropType::None> - Do(const PropId& id, T& var, StreamT& w) - { - var.template Enumerate>(w); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& s) - { - for (auto& v : var) - Write::Do, DNAE>(id, v, s); - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) - { - Write::Do(id, var, s); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& w) - { - for (T& v : vector) - Write::Do(id, v, w); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& w) - { - /* libc++ specializes vector as a bitstream */ - for (const T& v : vector) - w.writeBool(v); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& w) - { - if (buf) - w.writeUBytes(buf.get(), count); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::string& str, StreamT& w) - { - w.writeString(str); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) - { - w.writeString(str, count); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::wstring& str, StreamT& w) - { - Write::Do(id, str, w); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) - { - Write::Do(id, str, count, w); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) - { - w.seek(amount, whence); - } - static void DoAlign(atInt64 amount, StreamT& w) - { - w.writeZeroTo((w.position() + amount-1) / amount * amount); - } + size_t propCount = 0; + var.template Enumerate>(propCount); + __Write16(w, atUint16(propCount)); + var.template Enumerate>(w); + } + template + static typename std::enable_if_t<__IsDNARecord() && PropOp == PropType::None> Do(const PropId& id, T& var, + StreamT& w) { + var.template Enumerate>(w); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { + for (auto& v : var) + Write::Do, DNAE>(id, v, s); + } + template + static void DoSize(const PropId& id, T& var, StreamT& s) { + Write::Do(id, var, s); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, + const S& count, StreamT& w) { + for (T& v : vector) + Write::Do(id, v, w); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, + StreamT& w) { + /* libc++ specializes vector as a bitstream */ + for (const T& v : vector) + w.writeBool(v); + } + static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& w) { + if (buf) + w.writeUBytes(buf.get(), count); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::string& str, StreamT& w) { + w.writeString(str); + } + static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) { w.writeString(str, count); } + template + static typename std::enable_if_t> Do(const PropId& id, std::wstring& str, + StreamT& w) { + Write::Do(id, str, w); + } + template + static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) { + Write::Do(id, str, count, w); + } + static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) { w.seek(amount, whence); } + static void DoAlign(atInt64 amount, StreamT& w) { w.writeZeroTo((w.position() + amount - 1) / amount * amount); } }; -#define __WRITE_S(type, endian) template <> template <> inline void Write::Do \ - (const PropId& id, type& var, Write::StreamT& w) -#define __WRITE_WSTR_S(endian) template <> template <> inline void Write::Do \ - (const PropId& id, std::wstring& str, Write::StreamT& w) -#define __WRITE_WSTRC_S(endian) template <> template <> inline void Write::Do \ - (const PropId& id, std::wstring& str, atInt32 count, Write::StreamT& w) +#define __WRITE_S(type, endian) \ + template <> \ + template <> \ + inline void Write::Do(const PropId& id, type& var, Write::StreamT& w) +#define __WRITE_WSTR_S(endian) \ + template <> \ + template <> \ + inline void Write::Do(const PropId& id, std::wstring& str, Write::StreamT& w) +#define __WRITE_WSTRC_S(endian) \ + template <> \ + template <> \ + inline void Write::Do(const PropId& id, std::wstring& str, atInt32 count, Write::StreamT& w) __WRITE_S(bool, Endian::Big) { w.writeBool(var); } __WRITE_S(atInt8, Endian::Big) { w.writeByte(var); } __WRITE_S(atUint8, Endian::Big) { w.writeUByte(var); } @@ -666,109 +576,87 @@ __WRITE_WSTR_S(Endian::Little) { w.writeWStringLittle(str); } __WRITE_WSTRC_S(Endian::Little) { w.writeWStringLittle(str, count); } template -struct ReadYaml -{ - using PropT = std::conditional_t; - using StreamT = YAMLDocReader; - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& r) - { - using PODType = std::underlying_type_t; - ReadYaml::Do(id, *reinterpret_cast(&var), r); +struct ReadYaml { + using PropT = std::conditional_t; + using StreamT = YAMLDocReader; + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& r) { + using PODType = std::underlying_type_t; + ReadYaml::Do(id, *reinterpret_cast(&var), r); + } + template + static typename std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& r) { + using CastT = __CastPODType; + ReadYaml::Do(id, static_cast(var), r); + } + template + static typename std::enable_if_t<__IsDNARecord_v> Do(const PropId& id, T& var, StreamT& r) { + if (auto rec = r.enterSubRecord(id.name)) + var.template Enumerate>(r); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& r) { + size_t _count; + if (auto __v = r.enterSubVector(id.name, _count)) + for (size_t i = 0; i < _count && i < std::extent_v; ++i) + ReadYaml::Do, DNAE>({}, var[i], r); + } + template + static void DoSize(const PropId& id, T& var, StreamT& s) { + /* Squelch size field access */ + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, + const S& count, StreamT& r) { + size_t _count; + vector.clear(); + if (auto __v = r.enterSubVector(id.name, _count)) { + vector.reserve(_count); + for (size_t i = 0; i < _count; ++i) { + vector.emplace_back(); + ReadYaml::Do({}, vector.back(), r); + } } - template - static typename std::enable_if_t<__IsPODType_v> - Do(const PropId& id, T& var, StreamT& r) - { - using CastT = __CastPODType; - ReadYaml::Do(id, static_cast(var), r); + /* Horrible reference abuse (but it works) */ + const_cast(count) = vector.size(); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, + StreamT& r) { + /* libc++ specializes vector as a bitstream */ + size_t _count; + vector.clear(); + if (auto __v = r.enterSubVector(id.name, _count)) { + vector.reserve(_count); + for (size_t i = 0; i < _count; ++i) + vector.push_back(r.readBool(nullptr)); } - template - static typename std::enable_if_t<__IsDNARecord_v> - Do(const PropId& id, T& var, StreamT& r) - { - if (auto rec = r.enterSubRecord(id.name)) - var.template Enumerate>(r); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& r) - { - size_t _count; - if (auto __v = r.enterSubVector(id.name, _count)) - for (size_t i = 0; i < _count && i < std::extent_v; ++i) - ReadYaml::Do, DNAE>({}, var[i], r); - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) - { - /* Squelch size field access */ - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& r) - { - size_t _count; - vector.clear(); - if (auto __v = r.enterSubVector(id.name, _count)) - { - vector.reserve(_count); - for (size_t i = 0; i < _count; ++i) - { - vector.emplace_back(); - ReadYaml::Do({}, vector.back(), r); - } - } - /* Horrible reference abuse (but it works) */ - const_cast(count) = vector.size(); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& r) - { - /* libc++ specializes vector as a bitstream */ - size_t _count; - vector.clear(); - if (auto __v = r.enterSubVector(id.name, _count)) - { - vector.reserve(_count); - for (size_t i = 0; i < _count; ++i) - vector.push_back(r.readBool(nullptr)); - } - /* Horrible reference abuse (but it works) */ - const_cast(count) = vector.size(); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& r) - { - buf = r.readUBytes(id.name); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& r) - { - str = r.readString(id.name); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) - { - str = r.readString(id.name); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& r) - { - str = r.readWString(id.name); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) - { - str = r.readWString(id.name); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) {} - static void DoAlign(atInt64 amount, StreamT& r) {} + /* Horrible reference abuse (but it works) */ + const_cast(count) = vector.size(); + } + static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& r) { + buf = r.readUBytes(id.name); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { + str = r.readString(id.name); + } + static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) { str = r.readString(id.name); } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { + str = r.readWString(id.name); + } + template + static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) { + str = r.readWString(id.name); + } + static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) {} + static void DoAlign(atInt64 amount, StreamT& r) {} }; -#define __READ_YAML_S(type, endian) template <> template <> inline void ReadYaml::Do \ - (const PropId& id, type& var, ReadYaml::StreamT& r) +#define __READ_YAML_S(type, endian) \ + template <> \ + template <> \ + inline void ReadYaml::Do(const PropId& id, type& var, ReadYaml::StreamT& r) __READ_YAML_S(bool, Endian::Big) { var = r.readBool(id.name); } __READ_YAML_S(atInt8, Endian::Big) { var = r.readByte(id.name); } __READ_YAML_S(atUint8, Endian::Big) { var = r.readUByte(id.name); } @@ -805,91 +693,72 @@ __READ_YAML_S(atVec4f, Endian::Little) { var = r.readVec4f(id.name); } __READ_YAML_S(atVec4d, Endian::Little) { var = r.readVec4d(id.name); } template -struct WriteYaml -{ - using PropT = std::conditional_t; - using StreamT = YAMLDocWriter; - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& w) - { - using PODType = std::underlying_type_t; - WriteYaml::Do(id, *reinterpret_cast(&var), w); - } - template - static typename std::enable_if_t<__IsPODType_v> - Do(const PropId& id, T& var, StreamT& w) - { - using CastT = __CastPODType; - WriteYaml::Do(id, static_cast(const_cast&>(var)), w); - } - template - static typename std::enable_if_t<__IsDNARecord_v> - Do(const PropId& id, T& var, StreamT& w) - { - if (auto rec = w.enterSubRecord(id.name)) - var.template Enumerate>(w); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& var, StreamT& w) - { - if (auto __v = w.enterSubVector(id.name)) - for (auto& v : var) - WriteYaml::Do, DNAE>({}, v, w); - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) - { - /* Squelch size field access */ - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& w) - { - if (auto __v = w.enterSubVector(id.name)) - for (T& v : vector) - WriteYaml::Do(id, v, w); - } - template - static typename std::enable_if_t> - Do(const PropId& id, std::vector& vector, const S& count, StreamT& w) - { - /* libc++ specializes vector as a bitstream */ - if (auto __v = w.enterSubVector(id.name)) - for (const T& v : vector) - w.writeBool(nullptr, v); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& w) - { - w.writeUBytes(id.name, buf, count); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& w) - { - w.writeString(id.name, str); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) - { - w.writeString(id.name, str); - } - template - static typename std::enable_if_t> - Do(const PropId& id, T& str, StreamT& w) - { - w.writeWString(id.name, str); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) - { - w.writeWString(id.name, str); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) {} - static void DoAlign(atInt64 amount, StreamT& w) {} +struct WriteYaml { + using PropT = std::conditional_t; + using StreamT = YAMLDocWriter; + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& w) { + using PODType = std::underlying_type_t; + WriteYaml::Do(id, *reinterpret_cast(&var), w); + } + template + static typename std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& w) { + using CastT = __CastPODType; + WriteYaml::Do(id, static_cast(const_cast&>(var)), w); + } + template + static typename std::enable_if_t<__IsDNARecord_v> Do(const PropId& id, T& var, StreamT& w) { + if (auto rec = w.enterSubRecord(id.name)) + var.template Enumerate>(w); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& var, StreamT& w) { + if (auto __v = w.enterSubVector(id.name)) + for (auto& v : var) + WriteYaml::Do, DNAE>({}, v, w); + } + template + static void DoSize(const PropId& id, T& var, StreamT& s) { + /* Squelch size field access */ + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, + const S& count, StreamT& w) { + if (auto __v = w.enterSubVector(id.name)) + for (T& v : vector) + WriteYaml::Do(id, v, w); + } + template + static typename std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, + StreamT& w) { + /* libc++ specializes vector as a bitstream */ + if (auto __v = w.enterSubVector(id.name)) + for (const T& v : vector) + w.writeBool(nullptr, v); + } + static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& w) { + w.writeUBytes(id.name, buf, count); + } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& w) { + w.writeString(id.name, str); + } + static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) { w.writeString(id.name, str); } + template + static typename std::enable_if_t> Do(const PropId& id, T& str, StreamT& w) { + w.writeWString(id.name, str); + } + template + static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) { + w.writeWString(id.name, str); + } + static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) {} + static void DoAlign(atInt64 amount, StreamT& w) {} }; -#define __WRITE_YAML_S(type, endian) template <> template <> inline void WriteYaml::Do \ - (const PropId& id, type& var, WriteYaml::StreamT& w) +#define __WRITE_YAML_S(type, endian) \ + template <> \ + template <> \ + inline void WriteYaml::Do(const PropId& id, type& var, WriteYaml::StreamT& w) __WRITE_YAML_S(bool, Endian::Big) { w.writeBool(id.name, var); } __WRITE_YAML_S(atInt8, Endian::Big) { w.writeByte(id.name, var); } __WRITE_YAML_S(atUint8, Endian::Big) { w.writeUByte(id.name, var); } @@ -926,349 +795,345 @@ __WRITE_YAML_S(atVec4f, Endian::Little) { w.writeVec4f(id.name, var); } __WRITE_YAML_S(atVec4d, Endian::Little) { w.writeVec4d(id.name, var); } template -static inline void __Do(const PropId& id, T& var, typename Op::StreamT& s) -{ - Op::template Do(id, var, s); +static inline void __Do(const PropId& id, T& var, typename Op::StreamT& s) { + Op::template Do(id, var, s); } template -static inline void __DoSize(const PropId& id, T& var, typename Op::StreamT& s) -{ - Op::template DoSize(id, var, s); +static inline void __DoSize(const PropId& id, T& var, typename Op::StreamT& s) { + Op::template DoSize(id, var, s); } template -static inline void __Do(const PropId& id, std::vector& vector, const S& count, typename Op::StreamT& s) -{ - Op::template Do(id, vector, count, s); +static inline void __Do(const PropId& id, std::vector& vector, const S& count, typename Op::StreamT& s) { + Op::template Do(id, vector, count, s); } template -static inline void __Do(const PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) -{ - Op::Do(id, buf, count, s); +static inline void __Do(const PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) { + Op::Do(id, buf, count, s); } template -static inline void __Do(const PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) -{ - Op::Do(id, str, count, s); +static inline void __Do(const PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) { + Op::Do(id, str, count, s); } template -static inline void __Do(const PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) -{ - Op::template Do(id, str, count, s); +static inline void __Do(const PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { + Op::template Do(id, str, count, s); } template -static inline void __DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) -{ - Op::DoSeek(delta, whence, s); +static inline void __DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { + Op::DoSeek(delta, whence, s); } template -static inline void __DoAlign(atInt64 amount, typename Op::StreamT& s) -{ - Op::DoAlign(amount, s); +static inline void __DoAlign(atInt64 amount, typename Op::StreamT& s) { + Op::DoAlign(amount, s); } template -static inline void __Read(T& obj, athena::io::IStreamReader& r) -{ - __Do, T, T::DNAEndian>({}, obj, r); +static inline void __Read(T& obj, athena::io::IStreamReader& r) { + __Do, T, T::DNAEndian>({}, obj, r); } template -static inline void __Write(const T& obj, athena::io::IStreamWriter& w) -{ - __Do, T, T::DNAEndian>({}, const_cast(obj), w); +static inline void __Write(const T& obj, athena::io::IStreamWriter& w) { + __Do, T, T::DNAEndian>({}, const_cast(obj), w); } template -static inline void __BinarySize(const T& obj, size_t& s) -{ - __Do, T, T::DNAEndian>({}, const_cast(obj), s); +static inline void __BinarySize(const T& obj, size_t& s) { + __Do, T, T::DNAEndian>({}, const_cast(obj), s); } template -static inline void __PropCount(const T& obj, size_t& s) -{ - const_cast(obj).template Enumerate>(s); +static inline void __PropCount(const T& obj, size_t& s) { + const_cast(obj).template Enumerate>(s); } template -static inline void __ReadYaml(T& obj, athena::io::YAMLDocReader& r) -{ - obj.template Enumerate>(r); +static inline void __ReadYaml(T& obj, athena::io::YAMLDocReader& r) { + obj.template Enumerate>(r); } template -static inline void __WriteYaml(const T& obj, athena::io::YAMLDocWriter& w) -{ - const_cast(obj).template Enumerate>(w); +static inline void __WriteYaml(const T& obj, athena::io::YAMLDocWriter& w) { + const_cast(obj).template Enumerate>(w); } template -static inline void __ReadProp(T& obj, athena::io::IStreamReader& r) -{ - /* Read root 0xffffffff hash (hashed empty string) */ - T::DNAEndian == Endian::Big ? r.readUint32Big() : r.readUint32Little(); - atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little(); - atInt64 start = r.position(); - __Do, T, T::DNAEndian>({}, obj, r); - atInt64 actualRead = r.position() - start; - if (actualRead != size) - r.seek(size - actualRead); +static inline void __ReadProp(T& obj, athena::io::IStreamReader& r) { + /* Read root 0xffffffff hash (hashed empty string) */ + T::DNAEndian == Endian::Big ? r.readUint32Big() : r.readUint32Little(); + atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little(); + atInt64 start = r.position(); + __Do, T, T::DNAEndian>({}, obj, r); + atInt64 actualRead = r.position() - start; + if (actualRead != size) + r.seek(size - actualRead); } template -static inline void __WriteProp(const T& obj, athena::io::IStreamWriter& w) -{ - __Do, T, T::DNAEndian>({}, const_cast(obj), w); +static inline void __WriteProp(const T& obj, athena::io::IStreamWriter& w) { + __Do, T, T::DNAEndian>({}, const_cast(obj), w); } template -static inline void __BinarySizeProp(const T& obj, size_t& s) -{ - __Do, T, T::DNAEndian>({}, const_cast(obj), s); +static inline void __BinarySizeProp(const T& obj, size_t& s) { + __Do, T, T::DNAEndian>({}, const_cast(obj), s); } template -static inline void __ReadProp64(T& obj, athena::io::IStreamReader& r) -{ - /* Read root 0x0 hash (hashed empty string) */ - T::DNAEndian == Endian::Big ? r.readUint64Big() : r.readUint64Little(); - atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little(); - atInt64 start = r.position(); - __Do, T, T::DNAEndian>({}, obj, r); - atInt64 actualRead = r.position() - start; - if (actualRead != size) - r.seek(size - actualRead); +static inline void __ReadProp64(T& obj, athena::io::IStreamReader& r) { + /* Read root 0x0 hash (hashed empty string) */ + T::DNAEndian == Endian::Big ? r.readUint64Big() : r.readUint64Little(); + atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little(); + atInt64 start = r.position(); + __Do, T, T::DNAEndian>({}, obj, r); + atInt64 actualRead = r.position() - start; + if (actualRead != size) + r.seek(size - actualRead); } template -static inline void __WriteProp64(const T& obj, athena::io::IStreamWriter& w) -{ - __Do, T, T::DNAEndian>({}, const_cast(obj), w); +static inline void __WriteProp64(const T& obj, athena::io::IStreamWriter& w) { + __Do, T, T::DNAEndian>({}, const_cast(obj), w); } template -static inline void __BinarySizeProp64(const T& obj, size_t& s) -{ - __Do, T, T::DNAEndian>({}, const_cast(obj), s); +static inline void __BinarySizeProp64(const T& obj, size_t& s) { + __Do, T, T::DNAEndian>({}, const_cast(obj), s); } -} +} // namespace athena::io -#define AT_DECL_DNA \ -template \ -void Do(const athena::io::PropId& id, T& var, typename Op::StreamT& s) \ - { athena::io::__Do(id, var, s); } \ -template \ -void DoSize(const athena::io::PropId& id, T& var, typename Op::StreamT& s) \ - { athena::io::__DoSize(id, var, s); } \ -template \ -void Do(const athena::io::PropId& id, std::vector& var, const S& count, typename Op::StreamT& s) \ - { athena::io::__Do(id, var, count, s); } \ -template \ -void Do(const athena::io::PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) \ - { athena::io::__Do(id, buf, count, s); } \ -template \ -void Do(const athena::io::PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) \ - { athena::io::__Do(id, str, count, s); } \ -template \ -void Do(const athena::io::PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) \ - { athena::io::__Do(id, str, count, s); } \ -template \ -void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) \ - { athena::io::__DoSeek(delta, whence, s); } \ -template \ -void DoAlign(atInt64 amount, typename Op::StreamT& s) \ - { athena::io::__DoAlign(amount, s); } \ -template \ -void Enumerate(typename Op::StreamT& s); \ -static const char* DNAType(); \ -void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \ -void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \ -void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } +#define AT_DECL_DNA \ + template \ + void Do(const athena::io::PropId& id, T& var, typename Op::StreamT& s) { \ + athena::io::__Do(id, var, s); \ + } \ + template \ + void DoSize(const athena::io::PropId& id, T& var, typename Op::StreamT& s) { \ + athena::io::__DoSize(id, var, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::vector& var, const S& count, typename Op::StreamT& s) { \ + athena::io::__Do(id, var, count, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) { \ + athena::io::__Do(id, buf, count, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) { \ + athena::io::__Do(id, str, count, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { \ + athena::io::__Do(id, str, count, s); \ + } \ + template \ + void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { \ + athena::io::__DoSeek(delta, whence, s); \ + } \ + template \ + void DoAlign(atInt64 amount, typename Op::StreamT& s) { \ + athena::io::__DoAlign(amount, s); \ + } \ + template \ + void Enumerate(typename Op::StreamT& s); \ + static const char* DNAType(); \ + void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \ + void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \ + void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } -#define AT_DECL_DNA_YAML \ -AT_DECL_DNA \ -void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \ -void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } +#define AT_DECL_DNA_YAML \ + AT_DECL_DNA \ + void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \ + void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } -#define AT_DECL_EXPLICIT_DNA \ -AT_DECL_DNA \ -Delete __d; +#define AT_DECL_EXPLICIT_DNA \ + AT_DECL_DNA \ + Delete __d; -#define AT_DECL_EXPLICIT_DNA_YAML \ -AT_DECL_DNA_YAML \ -Delete __d; +#define AT_DECL_EXPLICIT_DNA_YAML \ + AT_DECL_DNA_YAML \ + Delete __d; -#define AT_DECL_DNAV const char* DNATypeV() const {return DNAType();} +#define AT_DECL_DNAV \ + const char* DNATypeV() const { return DNAType(); } -#define AT_SPECIALIZE_DNA(...) \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Read::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Write::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::BinarySize::StreamT& s); +#define AT_SPECIALIZE_DNA(...) \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Read::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Write::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::BinarySize::StreamT & s); -#define AT_SPECIALIZE_DNA_YAML(...) \ -AT_SPECIALIZE_DNA(__VA_ARGS__) \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::ReadYaml::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::WriteYaml::StreamT& s); +#define AT_SPECIALIZE_DNA_YAML(...) \ + AT_SPECIALIZE_DNA(__VA_ARGS__) \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::ReadYaml::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::WriteYaml::StreamT & s); -#define AT_DECL_PROPDNA \ -template \ -void Do(const athena::io::PropId& id, T& var, typename Op::StreamT& s) \ - { athena::io::__Do(id, var, s); } \ -template \ -void DoSize(const athena::io::PropId& id, T& var, typename Op::StreamT& s) \ - { athena::io::__DoSize(id, var, s); } \ -template \ -void Do(const athena::io::PropId& id, std::vector& var, const S& count, typename Op::StreamT& s) \ - { athena::io::__Do(id, var, count, s); } \ -template \ -void Do(const athena::io::PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) \ - { athena::io::__Do(id, buf, count, s); } \ -template \ -void Do(const athena::io::PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) \ - { athena::io::__Do(id, str, count, s); } \ -template \ -void Do(const athena::io::PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) \ - { athena::io::__Do(id, str, count, s); } \ -template \ -void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) \ - { athena::io::__DoSeek(delta, whence, s); } \ -template \ -void DoAlign(atInt64 amount, typename Op::StreamT& s) \ - { athena::io::__DoAlign(amount, s); } \ -template \ -void Enumerate(typename Op::StreamT& s); \ -template \ -bool Lookup(uint64_t hash, typename Op::StreamT& s); \ -static const char* DNAType(); \ -void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \ -void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \ -void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } \ -void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \ -void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } \ -void readProp(athena::io::IStreamReader& r) { athena::io::__ReadProp(*this, r); } \ -void writeProp(athena::io::IStreamWriter& w) const { athena::io::__WriteProp(*this, w); } \ -void binarySizeProp(size_t& s) const { athena::io::__BinarySizeProp(*this, s); } \ -void propCount(size_t& s) const { athena::io::__PropCount(*this, s); } \ -void readProp64(athena::io::IStreamReader& r) { athena::io::__ReadProp64(*this, r); } \ -void writeProp64(athena::io::IStreamWriter& w) const { athena::io::__WriteProp64(*this, w); } \ -void binarySizeProp64(size_t& s) const { athena::io::__BinarySizeProp64(*this, s); } \ +#define AT_DECL_PROPDNA \ + template \ + void Do(const athena::io::PropId& id, T& var, typename Op::StreamT& s) { \ + athena::io::__Do(id, var, s); \ + } \ + template \ + void DoSize(const athena::io::PropId& id, T& var, typename Op::StreamT& s) { \ + athena::io::__DoSize(id, var, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::vector& var, const S& count, typename Op::StreamT& s) { \ + athena::io::__Do(id, var, count, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) { \ + athena::io::__Do(id, buf, count, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) { \ + athena::io::__Do(id, str, count, s); \ + } \ + template \ + void Do(const athena::io::PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { \ + athena::io::__Do(id, str, count, s); \ + } \ + template \ + void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { \ + athena::io::__DoSeek(delta, whence, s); \ + } \ + template \ + void DoAlign(atInt64 amount, typename Op::StreamT& s) { \ + athena::io::__DoAlign(amount, s); \ + } \ + template \ + void Enumerate(typename Op::StreamT& s); \ + template \ + bool Lookup(uint64_t hash, typename Op::StreamT& s); \ + static const char* DNAType(); \ + void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \ + void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \ + void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } \ + void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \ + void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } \ + void readProp(athena::io::IStreamReader& r) { athena::io::__ReadProp(*this, r); } \ + void writeProp(athena::io::IStreamWriter& w) const { athena::io::__WriteProp(*this, w); } \ + void binarySizeProp(size_t& s) const { athena::io::__BinarySizeProp(*this, s); } \ + void propCount(size_t& s) const { athena::io::__PropCount(*this, s); } \ + void readProp64(athena::io::IStreamReader& r) { athena::io::__ReadProp64(*this, r); } \ + void writeProp64(athena::io::IStreamWriter& w) const { athena::io::__WriteProp64(*this, w); } \ + void binarySizeProp64(size_t& s) const { athena::io::__BinarySizeProp64(*this, s); } -#define AT_DECL_EXPLICIT_PROPDNA \ -AT_DECL_PROPDNA \ -Delete __d; +#define AT_DECL_EXPLICIT_PROPDNA \ + AT_DECL_PROPDNA \ + Delete __d; -#define AT_SPECIALIZE_PROPDNA(...) \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Read::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Write::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::BinarySize::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::ReadYaml::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::WriteYaml::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::Read::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Read::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::Write::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Write::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::BinarySize::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::BinarySize::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::PropCount::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::PropCount::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::ReadYaml::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::ReadYaml::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::WriteYaml::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::WriteYaml::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::Read::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Read::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::Write::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::Write::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::BinarySize::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::BinarySize::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::PropCount::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::PropCount::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::ReadYaml::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::ReadYaml::StreamT& s); \ -template bool __VA_ARGS__::Lookup>\ - (uint64_t hash, athena::io::WriteYaml::StreamT& s); \ -template void __VA_ARGS__::Enumerate>\ - (athena::io::WriteYaml::StreamT& s); +#define AT_SPECIALIZE_PROPDNA(...) \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Read::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Write::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::BinarySize::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::ReadYaml::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::WriteYaml::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::Read::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Read::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::Write::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Write::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::BinarySize::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::BinarySize::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::PropCount::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::PropCount::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::ReadYaml::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::ReadYaml::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::WriteYaml::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::WriteYaml::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::Read::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Read::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::Write::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::Write::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::BinarySize::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::BinarySize::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::PropCount::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::PropCount::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::ReadYaml::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::ReadYaml::StreamT & s); \ + template bool __VA_ARGS__::Lookup>( \ + uint64_t hash, athena::io::WriteYaml::StreamT & s); \ + template void __VA_ARGS__::Enumerate>( \ + athena::io::WriteYaml::StreamT & s); -#define AT_SUBDECL_DNA \ -void _read(athena::io::IStreamReader& r); \ -void _write(athena::io::IStreamWriter& w) const; \ -void _binarySize(size_t& s) const; \ -void _read(athena::io::YAMLDocReader& r); \ -void _write(athena::io::YAMLDocWriter& w) const; +#define AT_SUBDECL_DNA \ + void _read(athena::io::IStreamReader& r); \ + void _write(athena::io::IStreamWriter& w) const; \ + void _binarySize(size_t& s) const; \ + void _read(athena::io::YAMLDocReader& r); \ + void _write(athena::io::YAMLDocWriter& w) const; -#define AT_SUBDECL_DNA_YAML \ -AT_SUBDECL_DNA \ -void _read(athena::io::YAMLDocReader& r); \ -void _write(athena::io::YAMLDocWriter& w) const; +#define AT_SUBDECL_DNA_YAML \ + AT_SUBDECL_DNA \ + void _read(athena::io::YAMLDocReader& r); \ + void _write(athena::io::YAMLDocWriter& w) const; -#define AT_SUBSPECIALIZE_DNA(...) \ -template <> template <> \ -void __VA_ARGS__::Enumerate::BinarySize>(typename BinarySize::StreamT& s) \ -{ \ - _binarySize(s); \ -} \ -template <> template <> \ -void __VA_ARGS__::Enumerate::Read>(typename Read::StreamT& r) \ -{ \ - _read(r); \ -} \ -template <> template <> \ -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) \ -{ \ - _read(r); \ -} \ -template <> template <> \ -void __VA_ARGS__::Enumerate::WriteYaml>(typename WriteYaml::StreamT& w) \ -{ \ - _write(w); \ -} \ -AT_SUBSPECIALIZE_DNA(__VA_ARGS__) +#define AT_SUBSPECIALIZE_DNA(...) \ + template <> \ + template <> \ + void __VA_ARGS__::Enumerate::BinarySize>(typename BinarySize::StreamT & s) { \ + _binarySize(s); \ + } \ + template <> \ + template <> \ + void __VA_ARGS__::Enumerate::Read>(typename Read::StreamT & r) { \ + _read(r); \ + } \ + template <> \ + template <> \ + 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) { \ + _read(r); \ + } \ + template <> \ + template <> \ + void __VA_ARGS__::Enumerate::WriteYaml>(typename WriteYaml::StreamT & w) { \ + _write(w); \ + } \ + AT_SUBSPECIALIZE_DNA(__VA_ARGS__) diff --git a/include/athena/DNAYaml.hpp b/include/athena/DNAYaml.hpp index 90e9b36..99117cf 100644 --- a/include/athena/DNAYaml.hpp +++ b/include/athena/DNAYaml.hpp @@ -6,132 +6,116 @@ #include "FileReader.hpp" #include "FileWriter.hpp" -namespace athena::io -{ +namespace athena::io { template -static inline const char* __GetDNAName(const T& dna, - typename std::enable_if_t>* = 0) -{ - return dna.DNATypeV(); +static inline const char* __GetDNAName(const T& dna, typename std::enable_if_t>* = 0) { + return dna.DNATypeV(); } template -static inline const char* __GetDNAName(const T& dna, - typename std::enable_if_t>* = 0) -{ - return dna.DNAType(); +static inline const char* __GetDNAName(const T& dna, typename std::enable_if_t>* = 0) { + return dna.DNAType(); } template -static inline std::string ToYAMLString(const T& dna) -{ - YAMLDocWriter docWriter(__GetDNAName(dna)); +static inline std::string ToYAMLString(const T& dna) { + YAMLDocWriter docWriter(__GetDNAName(dna)); - std::string res; - yaml_emitter_set_output(docWriter.getEmitter(), (yaml_write_handler_t*)YAMLStdStringWriter, &res); - yaml_emitter_set_unicode(docWriter.getEmitter(), true); - yaml_emitter_set_width(docWriter.getEmitter(), -1); + std::string res; + yaml_emitter_set_output(docWriter.getEmitter(), (yaml_write_handler_t*)YAMLStdStringWriter, &res); + yaml_emitter_set_unicode(docWriter.getEmitter(), true); + yaml_emitter_set_width(docWriter.getEmitter(), -1); - dna.write(docWriter); - if (!docWriter.finish(nullptr)) - return std::string(); + dna.write(docWriter); + if (!docWriter.finish(nullptr)) + return std::string(); - return res; + return res; } template -static inline bool FromYAMLString(T& dna, std::string_view str) -{ - YAMLStdStringViewReaderState reader(str); - YAMLDocReader docReader; - yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); - if (!docReader.parse(nullptr)) - return false; - dna.read(docReader); - return true; +static inline bool FromYAMLString(T& dna, std::string_view str) { + YAMLStdStringViewReaderState reader(str); + YAMLDocReader docReader; + yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); + if (!docReader.parse(nullptr)) + return false; + dna.read(docReader); + return true; } -template -static inline bool ValidateFromYAMLString(std::string_view str) -{ - YAMLStdStringViewReaderState reader(str); - YAMLDocReader docReader; - yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); - bool retval = docReader.ValidateClassType(DNASubtype::DNAType()); - return retval; +template +static inline bool ValidateFromYAMLString(std::string_view str) { + YAMLStdStringViewReaderState reader(str); + YAMLDocReader docReader; + yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); + bool retval = docReader.ValidateClassType(DNASubtype::DNAType()); + return retval; } template -static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout) -{ - YAMLDocWriter docWriter(__GetDNAName(dna)); +static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout) { + YAMLDocWriter docWriter(__GetDNAName(dna)); - yaml_emitter_set_unicode(docWriter.getEmitter(), true); - yaml_emitter_set_width(docWriter.getEmitter(), -1); + yaml_emitter_set_unicode(docWriter.getEmitter(), true); + yaml_emitter_set_width(docWriter.getEmitter(), -1); - dna.write(docWriter); - return docWriter.finish(&fout); + dna.write(docWriter); + return docWriter.finish(&fout); } template static inline bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout, - void(T::*fn)(YAMLDocWriter& out)const) -{ - YAMLDocWriter docWriter(__GetDNAName(dna)); + void (T::*fn)(YAMLDocWriter& out) const) { + YAMLDocWriter docWriter(__GetDNAName(dna)); - yaml_emitter_set_unicode(docWriter.getEmitter(), true); - yaml_emitter_set_width(docWriter.getEmitter(), -1); + yaml_emitter_set_unicode(docWriter.getEmitter(), true); + yaml_emitter_set_width(docWriter.getEmitter(), -1); - (dna.*fn)(docWriter); - return docWriter.finish(&fout); + (dna.*fn)(docWriter); + return docWriter.finish(&fout); } template -static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin) -{ - YAMLDocReader docReader; - if (!docReader.parse(&fin)) - return false; - dna.read(docReader); - return true; +static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin) { + YAMLDocReader docReader; + if (!docReader.parse(&fin)) + return false; + dna.read(docReader); + return true; } template -static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin, - void(T::*fn)(YAMLDocReader& in)) -{ - YAMLDocReader docReader; - if (!docReader.parse(&fin)) - return false; - (dna.*fn)(docReader); - return true; +static inline bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin, void (T::*fn)(YAMLDocReader& in)) { + YAMLDocReader docReader; + if (!docReader.parse(&fin)) + return false; + (dna.*fn)(docReader); + return true; } template -static inline bool MergeToYAMLFile(const T& dna, const NameT& filename) -{ - athena::io::FileReader r(filename); - YAMLDocWriter docWriter(__GetDNAName(dna), r.isOpen() ? &r : nullptr); - r.close(); +static inline bool MergeToYAMLFile(const T& dna, const NameT& filename) { + athena::io::FileReader r(filename); + YAMLDocWriter docWriter(__GetDNAName(dna), r.isOpen() ? &r : nullptr); + r.close(); - dna.write(docWriter); - athena::io::FileWriter w(filename); - if (!w.isOpen()) - return false; - return docWriter.finish(&w); + dna.write(docWriter); + athena::io::FileWriter w(filename); + if (!w.isOpen()) + return false; + return docWriter.finish(&w); } template -static inline bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) -{ - YAMLDocReader reader; - 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); - return retval; -} - +static inline bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) { + YAMLDocReader reader; + 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); + return retval; } +} // namespace athena::io diff --git a/include/athena/Dir.hpp b/include/athena/Dir.hpp index c42d5de..e18d080 100644 --- a/include/athena/Dir.hpp +++ b/include/athena/Dir.hpp @@ -8,30 +8,26 @@ typedef int mode_t; #endif -namespace athena -{ -class Dir -{ +namespace athena { +class Dir { public: - explicit Dir(std::string_view path); + explicit Dir(std::string_view path); - std::string absolutePath() const; - static inline std::string absolutePath(std::string_view path) - { return Dir(path).absolutePath(); } + std::string absolutePath() const; + static inline std::string absolutePath(std::string_view path) { return Dir(path).absolutePath(); } - bool isDir() const; - static bool isDir(std::string_view dir) - { return Dir(dir).isDir(); } + bool isDir() const; + static bool isDir(std::string_view dir) { return Dir(dir).isDir(); } - std::vector files() const; + std::vector files() const; + + bool cd(std::string_view path); + bool rm(std::string_view path); + bool touch(); + static bool mkdir(std::string_view dir, mode_t mode = 0755); + static bool mkpath(std::string_view path, mode_t mode = 0755); - bool cd(std::string_view path); - bool rm(std::string_view path); - bool touch(); - static bool mkdir(std::string_view dir, mode_t mode = 0755); - static bool mkpath(std::string_view path, mode_t mode = 0755); private: - std::string m_path; + std::string m_path; }; -} - +} // namespace athena diff --git a/include/athena/FileInfo.hpp b/include/athena/FileInfo.hpp index 2d4e8ec..1b8e01b 100644 --- a/include/athena/FileInfo.hpp +++ b/include/athena/FileInfo.hpp @@ -4,54 +4,41 @@ #include "athena/Global.hpp" -namespace athena -{ -class FileInfo -{ +namespace athena { +class FileInfo { public: - explicit FileInfo(std::string_view path = {}); + explicit FileInfo(std::string_view path = {}); - std::string absolutePath() const; - static inline std::string absolutePath(std::string_view lnk) - { return FileInfo(lnk).absolutePath(); } + std::string absolutePath() const; + static inline std::string absolutePath(std::string_view lnk) { return FileInfo(lnk).absolutePath(); } - std::string absoluteFilePath() const; - static inline std::string absoluteFilePath(std::string_view path) - { return FileInfo(path).absoluteFilePath(); } + std::string absoluteFilePath() const; + static inline std::string absoluteFilePath(std::string_view path) { return FileInfo(path).absoluteFilePath(); } - std::string filename() const; - static inline std::string filename(std::string_view path) - { return FileInfo(path).filename(); } + std::string filename() const; + static inline std::string filename(std::string_view path) { return FileInfo(path).filename(); } - std::string path() const { return m_path; } - static inline std::string path(std::string_view path) - { return FileInfo(path).path(); } + std::string path() const { return m_path; } + static inline std::string path(std::string_view path) { return FileInfo(path).path(); } - std::string extension() const; - static inline std::string extension(std::string_view path) - { return FileInfo(path).extension(); } + std::string extension() const; + static inline std::string extension(std::string_view path) { return FileInfo(path).extension(); } - atUint64 size() const; - static inline atUint64 size(std::string_view path) - { return FileInfo(path).size(); } + atUint64 size() const; + static inline atUint64 size(std::string_view path) { return FileInfo(path).size(); } - bool exists() const; - static inline bool exists(std::string_view path) - { return FileInfo(path).exists(); } + bool exists() const; + static inline bool exists(std::string_view path) { return FileInfo(path).exists(); } - bool isLink() const; - static inline bool isLink(std::string_view lnk) - { return FileInfo(lnk).isLink(); } - bool isFile() const; - static inline bool isFile(std::string_view path) - { return FileInfo(path).isFile(); } + bool isLink() const; + static inline bool isLink(std::string_view lnk) { return FileInfo(lnk).isLink(); } + bool isFile() const; + static inline bool isFile(std::string_view path) { return FileInfo(path).isFile(); } - bool touch() const; - static inline bool touch(std::string_view path) - { return FileInfo(path).touch(); } + bool touch() const; + static inline bool touch(std::string_view path) { return FileInfo(path).touch(); } private: - std::string m_path; + std::string m_path; }; -} - +} // namespace athena diff --git a/include/athena/FileReader.hpp b/include/athena/FileReader.hpp index f3ba82e..16e1f7f 100644 --- a/include/athena/FileReader.hpp +++ b/include/athena/FileReader.hpp @@ -13,71 +13,66 @@ #include #include "athena/IStreamReader.hpp" -namespace athena::io -{ -class FileReader : public IStreamReader -{ +namespace athena::io { +class FileReader : public IStreamReader { public: - FileReader(std::string_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr=true); - FileReader(std::wstring_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr=true); - virtual ~FileReader(); + FileReader(std::string_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr = true); + FileReader(std::wstring_view filename, atInt32 cacheSize = (32 * 1024), bool globalErr = true); + virtual ~FileReader(); - inline std::string filename() const - { + inline std::string filename() const { #if _WIN32 - return utility::wideToUtf8(m_filename); + return utility::wideToUtf8(m_filename); #else - return m_filename; + return m_filename; #endif - } + } - inline std::wstring wfilename() const - { + inline std::wstring wfilename() const { #if _WIN32 - return m_filename; + return m_filename; #else - return utility::utf8ToWide(m_filename); + return utility::utf8ToWide(m_filename); #endif - } + } - void open(); - void close(); - inline bool isOpen() const - {return m_fileHandle != 0;} - bool save(); - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - atUint64 position() const; - atUint64 length() const; - atUint64 readUBytesToBuf(void* buf, atUint64 len); + void open(); + void close(); + inline bool isOpen() const { return m_fileHandle != 0; } + bool save(); + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + atUint64 position() const; + atUint64 length() const; + atUint64 readUBytesToBuf(void* buf, atUint64 len); - void setCacheSize(const atInt32 blockSize); + void setCacheSize(const atInt32 blockSize); #if _WIN32 - using HandleType = HANDLE; + using HandleType = HANDLE; #else - using HandleType = FILE*; + using HandleType = FILE*; #endif - HandleType _fileHandle() {return m_fileHandle;} + HandleType _fileHandle() { return m_fileHandle; } + protected: #if _WIN32 - std::wstring m_filename; + std::wstring m_filename; #else - std::string m_filename; + std::string m_filename; #endif - HandleType m_fileHandle; - std::unique_ptr m_cacheData; - atInt32 m_blockSize; - atInt32 m_curBlock; - atUint64 m_offset; - bool m_globalErr; + HandleType m_fileHandle; + std::unique_ptr m_cacheData; + atInt32 m_blockSize; + atInt32 m_curBlock; + atUint64 m_offset; + bool m_globalErr; }; -} // Athena +} // namespace athena::io #ifndef FILEREADER_BASE -#define FILEREADER_BASE() \ -private: \ - typedef athena::io::FileReader base +#define FILEREADER_BASE() \ +private: \ + typedef athena::io::FileReader base #endif // FILEREADER_BASE - diff --git a/include/athena/FileWriter.hpp b/include/athena/FileWriter.hpp index 116c795..3d8cf38 100644 --- a/include/athena/FileWriter.hpp +++ b/include/athena/FileWriter.hpp @@ -10,112 +10,107 @@ #endif #include "athena/IStreamWriter.hpp" -namespace athena::io -{ -class FileWriter : public IStreamWriter -{ +namespace athena::io { +class FileWriter : public IStreamWriter { public: - FileWriter(std::string_view filename, bool overwrite = true, bool globalErr=true); - FileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr=true); - virtual ~FileWriter(); + FileWriter(std::string_view filename, bool overwrite = true, bool globalErr = true); + FileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr = true); + virtual ~FileWriter(); - inline std::string filename() const - { + inline std::string filename() const { #if _WIN32 - return utility::wideToUtf8(m_filename); + return utility::wideToUtf8(m_filename); #else - return m_filename; + return m_filename; #endif - } - inline std::wstring wfilename() const - { + } + inline std::wstring wfilename() const { #if _WIN32 - return m_filename; + return m_filename; #else - return utility::utf8ToWide(m_filename); + return utility::utf8ToWide(m_filename); #endif - } + } - void open(bool overwrite = true); - void close(); - inline bool isOpen() const - {return m_fileHandle != 0;} - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - atUint64 position() const; - atUint64 length() const; - void writeUBytes(const atUint8* data, atUint64 len); + void open(bool overwrite = true); + void close(); + inline bool isOpen() const { return m_fileHandle != 0; } + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + atUint64 position() const; + atUint64 length() const; + void writeUBytes(const atUint8* data, atUint64 len); #if _WIN32 - using HandleType = HANDLE; + using HandleType = HANDLE; #else - using HandleType = FILE*; + using HandleType = FILE*; #endif - HandleType _fileHandle() {return m_fileHandle;} + HandleType _fileHandle() { return m_fileHandle; } + private: #if _WIN32 - std::wstring m_filename; + std::wstring m_filename; #else - std::string m_filename; + std::string m_filename; #endif - HandleType m_fileHandle; - bool m_globalErr; + HandleType m_fileHandle; + bool m_globalErr; }; -class TransactionalFileWriter : public IStreamWriter -{ +class TransactionalFileWriter : public IStreamWriter { #if _WIN32 - std::wstring m_filename; + std::wstring m_filename; #else - std::string m_filename; + std::string m_filename; #endif - bool m_overwrite, m_globalErr; - std::vector m_deferredBuffer; - atUint64 m_position = 0; + bool m_overwrite, m_globalErr; + std::vector m_deferredBuffer; + atUint64 m_position = 0; + public: - TransactionalFileWriter(std::string_view filename, bool overwrite = true, bool globalErr=true) - : m_overwrite(overwrite), m_globalErr(globalErr) - { + TransactionalFileWriter(std::string_view filename, bool overwrite = true, bool globalErr = true) + : m_overwrite(overwrite), m_globalErr(globalErr) { #if _WIN32 - m_filename = utility::utf8ToWide(filename); + m_filename = utility::utf8ToWide(filename); #else - m_filename = filename; + m_filename = filename; #endif - } - TransactionalFileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr=true) - : m_overwrite(overwrite), m_globalErr(globalErr) - { + } + TransactionalFileWriter(std::wstring_view filename, bool overwrite = true, bool globalErr = true) + : m_overwrite(overwrite), m_globalErr(globalErr) { #if _WIN32 - m_filename = filename; + m_filename = filename; #else - m_filename = utility::wideToUtf8(filename); + m_filename = utility::wideToUtf8(filename); #endif + } + + void flush() { + if (m_deferredBuffer.size()) { + FileWriter w(m_filename, m_overwrite, m_globalErr); + w.writeUBytes(m_deferredBuffer.data(), m_deferredBuffer.size()); + cancel(); } + } - void flush() - { - if (m_deferredBuffer.size()) - { - FileWriter w(m_filename, m_overwrite, m_globalErr); - w.writeUBytes(m_deferredBuffer.data(), m_deferredBuffer.size()); - cancel(); - } - } + void cancel() { + m_deferredBuffer.clear(); + m_position = 0; + } - void cancel() { m_deferredBuffer.clear(); m_position = 0; } + inline atUint64 position() const { return m_position; } + inline atUint64 length() const { return m_deferredBuffer.size(); } + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + void writeUBytes(const atUint8* data, atUint64 len); - inline atUint64 position() const { return m_position; } - inline atUint64 length() const { return m_deferredBuffer.size(); } - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - void writeUBytes(const atUint8* data, atUint64 len); - - ~TransactionalFileWriter() { flush(); } + ~TransactionalFileWriter() { flush(); } }; -} // Athena +} // namespace athena::io #ifndef FILEWRITER_BASE -#define FILEWRITER_BASE() \ -private: \ - typedef athena::io::FileWriter base; +#define FILEWRITER_BASE() \ +private: \ + typedef athena::io::FileWriter base; #endif // FILEWRITER_BASE diff --git a/include/athena/Global.hpp b/include/athena/Global.hpp index cea6b45..c99865b 100644 --- a/include/athena/Global.hpp +++ b/include/athena/Global.hpp @@ -82,80 +82,57 @@ typedef struct stat64 atStat64_t; #ifndef ENABLE_BITWISE_ENUM #define ENABLE_BITWISE_ENUM(type) \ - constexpr type operator|(type a, type b) \ - { \ - using T = std::underlying_type_t; \ - return type(static_cast(a) | static_cast(b)); \ - } \ - constexpr type operator&(type a, type b) \ - { \ - using T = std::underlying_type_t; \ - return type(static_cast(a) & static_cast(b)); \ - } \ - inline type& operator|=(type& a, const 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) \ - { \ - using T = std::underlying_type_t; \ - a = type(static_cast(a) & static_cast(b)); \ - return a; \ - } \ - inline type operator~(const type& key) \ - { \ - using T = std::underlying_type_t; \ - return type(~static_cast(key)); \ - } + constexpr type operator|(type a, type b) { \ + using T = std::underlying_type_t; \ + return type(static_cast(a) | static_cast(b)); \ + } \ + constexpr type operator&(type a, type b) { \ + using T = std::underlying_type_t; \ + return type(static_cast(a) & static_cast(b)); \ + } \ + inline type& operator|=(type& a, const 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) { \ + using T = std::underlying_type_t; \ + a = type(static_cast(a) & static_cast(b)); \ + return a; \ + } \ + inline type operator~(const type& key) { \ + using T = std::underlying_type_t; \ + return type(~static_cast(key)); \ + } #endif -namespace athena -{ -namespace error -{ -enum class Level -{ - Message, - Warning, - Error, - Fatal -}; +namespace athena { +namespace error { +enum class Level { Message, Warning, Error, Fatal }; } -enum SeekOrigin -{ - Begin, - Current, - End -}; +enum SeekOrigin { Begin, Current, End }; -enum Endian -{ - Little, - Big -}; +enum Endian { Little, Big }; -namespace io -{ +namespace io { template struct DNA; template struct DNAV; template -using __IsDNARecord = typename std::disjunction, T>, - std::is_base_of, T>>; +using __IsDNARecord = + typename std::disjunction, T>, std::is_base_of, T>>; template inline constexpr bool __IsDNARecord_v = __IsDNARecord::value; template -using __IsDNAVRecord = typename std::disjunction, T>, - std::is_base_of, T>>; +using __IsDNAVRecord = + typename std::disjunction, T>, std::is_base_of, T>>; template inline constexpr bool __IsDNAVRecord_v = __IsDNAVRecord::value; -} -} // Athena +} // namespace io +} // namespace athena typedef void (*atEXCEPTION_HANDLER)(athena::error::Level level, const char* file, const char* function, int line, const char* fmt, ...); @@ -173,91 +150,80 @@ std::ostream& operator<<(std::ostream& os, const athena::Endian& endian); #ifdef _MSC_VER #ifndef NDEBUG #define atDebug(fmt, ...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ + } while (0) #else #define atDebug(fmt, ...) #endif #define atMessage(fmt, ...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ + } while (0) #define atWarning(fmt, ...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ + } while (0) #define atError(fmt, ...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ + } while (0) #define atFatal(fmt, ...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ + } while (0) #elif defined(__GNUC__) #ifndef NDEBUG #define atDebug(fmt...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ + } while (0) #else // _MSC_VER #define atDebug(fmt, ...) #endif // NDEBUG #define atMessage(fmt...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ + } while (0) #define atWarning(fmt...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ + } while (0) #define atError(fmt...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ + } while (0) #define atFatal(fmt...) \ - do \ - { \ - atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ - if (__handler) \ - __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ - } while (0) + do { \ + atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ + if (__handler) \ + __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ + } while (0) #endif // defined(__GNUC__) - diff --git a/include/athena/IStream.hpp b/include/athena/IStream.hpp index ffd356f..6b790fe 100644 --- a/include/athena/IStream.hpp +++ b/include/athena/IStream.hpp @@ -2,31 +2,30 @@ #include "Global.hpp" -namespace athena::io -{ +namespace athena::io { std::ostream& operator<<(std::ostream& os, Endian& endian); -class IStream -{ +class IStream { public: - virtual ~IStream() = default; + virtual ~IStream() = default; + + void setEndian(Endian endian) { m_endian = endian; } + Endian endian() const { return m_endian; } + bool isBigEndian() const { return (m_endian == Endian::Big); } + bool isLittleEndian() const { return (m_endian == Endian::Little); } + virtual void seek(atInt64, SeekOrigin) = 0; + virtual bool atEnd() const = 0; + virtual atUint64 position() const = 0; + virtual atUint64 length() const = 0; + bool hasError() const { return m_hasError; } - void setEndian(Endian endian) { m_endian = endian; } - Endian endian() const { return m_endian; } - bool isBigEndian() const { return (m_endian == Endian::Big); } - bool isLittleEndian() const { return (m_endian == Endian::Little); } - virtual void seek(atInt64, SeekOrigin) = 0; - virtual bool atEnd() const = 0; - virtual atUint64 position() const = 0; - virtual atUint64 length() const = 0; - bool hasError() const { return m_hasError; } protected: - void setError() { m_hasError = true; } - bool m_hasError = false; + void setError() { m_hasError = true; } + bool m_hasError = false; #if __BYTE_ORDER == __BIG_ENDIAN - Endian m_endian = Big; + Endian m_endian = Big; #else - Endian m_endian = Little; + Endian m_endian = Little; #endif }; -} +} // namespace athena::io diff --git a/include/athena/IStreamReader.hpp b/include/athena/IStreamReader.hpp index f619d8a..6b8e73d 100644 --- a/include/athena/IStreamReader.hpp +++ b/include/athena/IStreamReader.hpp @@ -6,1231 +6,1201 @@ #include "Utility.hpp" #include "IStream.hpp" -namespace athena::io -{ -/** @brief The IStreamReader class defines a basic API for reading from streams, Implementors are provided with one pure virtual - * function that must be implemented in order to interact with the stream. +namespace athena::io { +/** @brief The IStreamReader class defines a basic API for reading from streams, Implementors are provided with one pure + * virtual function that must be implemented in order to interact with the stream. * - * Most implementing classes will only need to implement IStreamReader::readUBytesToBuf(void*, atUint64) for basic stream intearaction + * Most implementing classes will only need to implement IStreamReader::readUBytesToBuf(void*, atUint64) for basic + * stream intearaction */ -class IStreamReader : public IStream -{ +class IStreamReader : public IStream { public: - virtual ~IStreamReader() = default; + virtual ~IStreamReader() = default; - /** @brief Sets the buffers position relative to the specified position.
- * It seeks relative to the current position by default. - * @param position where in the buffer to seek - * @param origin The Origin to seek relative to - */ - virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)=0; + /** @brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * @param position where in the buffer to seek + * @param origin The Origin to seek relative to + */ + virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current) = 0; - /** @brief Sets the buffer's position relative to the next 64-byte aligned position.
- */ - void seekAlign64() {seek(ROUND_UP_64(position()), SeekOrigin::Begin);} + /** @brief Sets the buffer's position relative to the next 64-byte aligned position.
+ */ + void seekAlign64() { seek(ROUND_UP_64(position()), SeekOrigin::Begin); } - /** @brief Sets the buffers position relative to the next 32-byte aligned position.
- */ - void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);} + /** @brief Sets the buffers position relative to the next 32-byte aligned position.
+ */ + void seekAlign32() { seek(ROUND_UP_32(position()), SeekOrigin::Begin); } - /** @brief Sets the buffer's position relative to the next 16-byte aligned position.
- */ - void seekAlign16() {seek(ROUND_UP_16(position()), SeekOrigin::Begin); } + /** @brief Sets the buffer's position relative to the next 16-byte aligned position.
+ */ + void seekAlign16() { seek(ROUND_UP_16(position()), SeekOrigin::Begin); } - /** @brief Sets the buffer's position relative to the next 4-byte aligned position.
- */ - void seekAlign4() {seek(ROUND_UP_4(position()), SeekOrigin::Begin); } + /** @brief Sets the buffer's position relative to the next 4-byte aligned position.
+ */ + void seekAlign4() { seek(ROUND_UP_4(position()), SeekOrigin::Begin); } - /** @brief Returns whether or not the stream is at the end. - * - * @return True if at end; False otherwise. - */ - bool atEnd() const - {return position() >= length();} + /** @brief Returns whether or not the stream is at the end. + * + * @return True if at end; False otherwise. + */ + bool atEnd() const { return position() >= length(); } - /** @brief Returns the current position in the stream. - * - * @return The current position in the stream. - */ - virtual atUint64 position() const=0; + /** @brief Returns the current position in the stream. + * + * @return The current position in the stream. + */ + virtual atUint64 position() const = 0; - /** @brief Returns the length of the file. - * - * @return True length of the file. - */ - virtual atUint64 length() const=0; + /** @brief Returns the length of the file. + * + * @return True length of the file. + */ + virtual atUint64 length() const = 0; - /** @brief Reads a byte at the current position and advances the current position - * - * @return The value at the current position - */ - atInt8 readByte() {atInt8 val; readUBytesToBuf(&val, 1); return val;} - template - atInt8 readVal(typename std::enable_if::value>::type* = 0) - {return readByte();} - template - atInt8 readValLittle(typename std::enable_if::value>::type* = 0) - {return readByte();} - template - atInt8 readValBig(typename std::enable_if::value>::type* = 0) - {return readByte();} + /** @brief Reads a byte at the current position and advances the current position + * + * @return The value at the current position + */ + atInt8 readByte() { + atInt8 val; + readUBytesToBuf(&val, 1); + return val; + } + template + atInt8 readVal(typename std::enable_if::value>::type* = 0) { + return readByte(); + } + template + atInt8 readValLittle(typename std::enable_if::value>::type* = 0) { + return readByte(); + } + template + atInt8 readValBig(typename std::enable_if::value>::type* = 0) { + return readByte(); + } - /** @brief Reads a byte at the current position and advances the current position - * - * @return The value at the current position - */ - atUint8 readUByte() {return readByte();} - template - atUint8 readVal(typename std::enable_if::value>::type* = 0) - {return readUByte();} - template - atUint8 readValLittle(typename std::enable_if::value>::type* = 0) - {return readUByte();} - template - atUint8 readValBig(typename std::enable_if::value>::type* = 0) - {return readUByte();} + /** @brief Reads a byte at the current position and advances the current position + * + * @return The value at the current position + */ + atUint8 readUByte() { return readByte(); } + template + atUint8 readVal(typename std::enable_if::value>::type* = 0) { + return readUByte(); + } + template + atUint8 readValLittle(typename std::enable_if::value>::type* = 0) { + return readUByte(); + } + template + atUint8 readValBig(typename std::enable_if::value>::type* = 0) { + return readUByte(); + } - /** @brief Reads a byte at the current position and advances the current position. - * - * @return The buffer at the current position from the given length. - */ - std::unique_ptr readBytes(atUint64 length) - { - atInt8* buf = new atInt8[length]; - readUBytesToBuf(buf, length); - return std::unique_ptr(buf); + /** @brief Reads a byte at the current position and advances the current position. + * + * @return The buffer at the current position from the given length. + */ + std::unique_ptr readBytes(atUint64 length) { + atInt8* buf = new atInt8[length]; + readUBytesToBuf(buf, length); + return std::unique_ptr(buf); + } + + /** @brief Reads a byte at the current position and advances the current position. + * + * @return The buffer at the current position from the given length. + */ + std::unique_ptr readUBytes(atUint64 length) { + atUint8* buf = new atUint8[length]; + readUBytesToBuf(buf, length); + return std::unique_ptr(buf); + } + + /** @brief Attempts to read a fixed length of data into a pre-allocated buffer. + * @param buf The buffer to read into + * @param len The length of the buffer + * @return How much data was actually read, useful for detecting read errors. + */ + atUint64 readBytesToBuf(void* buf, atUint64 len) { return readUBytesToBuf(buf, len); } + + /** @brief Attempts to read a fixed length of data into a pre-allocated buffer, this function is client defined + * and must be implemented. + * @param buf The buffer to read into + * @param len The length of the buffer + * @return How much data was actually read, useful for detecting read errors. + */ + virtual atUint64 readUBytesToBuf(void* buf, atUint64 len) = 0; + + /** @brief Reads a Int16 and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt16 readInt16() { + atInt16 val; + readUBytesToBuf(&val, 2); + return m_endian == Big ? utility::BigInt16(val) : utility::LittleInt16(val); + } + template + atInt16 readVal(typename std::enable_if::value>::type* = 0) { + return readInt16(); + } + + /** @brief Reads a Int16 and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt16 readInt16Little() { + atInt16 val; + readUBytesToBuf(&val, 2); + return utility::LittleInt16(val); + } + template + atInt16 readValLittle(typename std::enable_if::value>::type* = 0) { + return readInt16Little(); + } + + /** @brief Reads a Int16 and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt16 readInt16Big() { + atInt16 val; + readUBytesToBuf(&val, 2); + return utility::BigInt16(val); + } + template + atInt16 readValBig(typename std::enable_if::value>::type* = 0) { + return readInt16Big(); + } + + /** @brief Reads a Uint16 and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint16 readUint16() { return readInt16(); } + template + atUint16 readVal(typename std::enable_if::value>::type* = 0) { + return readUint16(); + } + + /** @brief Reads a Uint16 and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint16 readUint16Little() { + atUint16 val; + readUBytesToBuf(&val, 2); + return utility::LittleUint16(val); + } + template + atUint16 readValLittle(typename std::enable_if::value>::type* = 0) { + return readUint16Little(); + } + + /** @brief Reads a Uint16 and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint16 readUint16Big() { + atUint16 val; + readUBytesToBuf(&val, 2); + return utility::BigUint16(val); + } + template + atUint16 readValBig(typename std::enable_if::value>::type* = 0) { + return readUint16Big(); + } + + /** @brief Reads a Int32 and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt32 readInt32() { + atInt32 val; + readUBytesToBuf(&val, 4); + return m_endian == Big ? utility::BigInt32(val) : utility::LittleInt32(val); + } + template + atInt32 readVal(typename std::enable_if::value>::type* = 0) { + return readInt32(); + } + + /** @brief Reads a Int32 and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt32 readInt32Little() { + atInt32 val; + readUBytesToBuf(&val, 4); + return utility::LittleInt32(val); + } + template + atInt32 readValLittle(typename std::enable_if::value>::type* = 0) { + return readInt32Little(); + } + + /** @brief Reads a Int32 and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt32 readInt32Big() { + atInt32 val; + readUBytesToBuf(&val, 4); + return utility::BigInt32(val); + } + template + atInt32 readValBig(typename std::enable_if::value>::type* = 0) { + return readInt32Big(); + } + + /** @brief Reads a Uint32 and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint32 readUint32() { return readInt32(); } + template + atUint32 readVal(typename std::enable_if::value>::type* = 0) { + return readUint32(); + } + + /** @brief Reads a Uint32 and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint32 readUint32Little() { + atUint32 val; + readUBytesToBuf(&val, 4); + return utility::LittleUint32(val); + } + template + atInt32 readValLittle(typename std::enable_if::value>::type* = 0) { + return readUint32Little(); + } + + /** @brief Reads a Uint32 and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint32 readUint32Big() { + atUint32 val; + readUBytesToBuf(&val, 4); + return utility::BigUint32(val); + } + template + atUint32 readValBig(typename std::enable_if::value>::type* = 0) { + return readUint32Big(); + } + + /** @brief Reads a Int64 and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt64 readInt64() { + atInt64 val; + readUBytesToBuf(&val, 8); + return m_endian == Big ? utility::BigInt64(val) : utility::LittleInt64(val); + } + template + atInt64 readVal(typename std::enable_if::value>::type* = 0) { + return readInt64(); + } + + /** @brief Reads a Int64 and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt64 readInt64Little() { + atInt64 val; + readUBytesToBuf(&val, 8); + return utility::LittleInt64(val); + } + template + atInt64 readValLittle(typename std::enable_if::value>::type* = 0) { + return readInt64Little(); + } + + /** @brief Reads a Int64 and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atInt64 readInt64Big() { + atInt64 val; + readUBytesToBuf(&val, 8); + return utility::BigInt64(val); + } + template + atInt64 readValBig(typename std::enable_if::value>::type* = 0) { + return readInt64Big(); + } + + /** @brief Reads a Uint64 and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint64 readUint64() { return readInt64(); } + template + atUint64 readVal(typename std::enable_if::value>::type* = 0) { + return readUint64(); + } + + /** @brief Reads a Uint64 and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint64 readUint64Little() { + atUint64 val; + readUBytesToBuf(&val, 8); + return utility::LittleUint64(val); + } + template + atUint64 readValLittle(typename std::enable_if::value>::type* = 0) { + return readUint64Little(); + } + + /** @brief Reads a Uint64 and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atUint64 readUint64Big() { + atUint64 val; + readUBytesToBuf(&val, 8); + return utility::BigUint64(val); + } + template + atUint64 readValBig(typename std::enable_if::value>::type* = 0) { + return readUint64Big(); + } + + /** @brief Reads a float and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + float readFloat() { + float val; + readUBytesToBuf(&val, 4); + return m_endian == Big ? utility::BigFloat(val) : utility::LittleFloat(val); + } + template + float readVal(typename std::enable_if::value>::type* = 0) { + return readFloat(); + } + + /** @brief Reads a float and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + float readFloatLittle() { + float val; + readUBytesToBuf(&val, 4); + return utility::LittleFloat(val); + } + template + float readValLittle(typename std::enable_if::value>::type* = 0) { + return readFloatLittle(); + } + + /** @brief Reads a float and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + float readFloatBig() { + float val; + readUBytesToBuf(&val, 4); + return utility::BigFloat(val); + } + template + float readValBig(typename std::enable_if::value>::type* = 0) { + return readFloatBig(); + } + + /** @brief Reads a double and swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + double readDouble() { + double val; + readUBytesToBuf(&val, 8); + return m_endian == Big ? utility::BigDouble(val) : utility::LittleDouble(val); + } + template + double readVal(typename std::enable_if::value>::type* = 0) { + return readDouble(); + } + + /** @brief Reads a double and swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + double readDoubleLittle() { + double val; + readUBytesToBuf(&val, 8); + return utility::LittleDouble(val); + } + template + double readValLittle(typename std::enable_if::value>::type* = 0) { + return readDoubleLittle(); + } + + /** @brief Reads a double and swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + double readDoubleBig() { + double val; + readUBytesToBuf(&val, 8); + return utility::BigDouble(val); + } + template + double readValBig(typename std::enable_if::value>::type* = 0) { + return readDoubleBig(); + } + + /** @brief Reads a bool and advances the current position + * + * @return The value at the current address + */ + bool readBool() { + atUint8 val; + readUBytesToBuf(&val, 1); + return val != 0; + } + template + bool readVal(typename std::enable_if::value>::type* = 0) { + return readBool(); + } + template + bool readValLittle(typename std::enable_if::value>::type* = 0) { + return readBool(); + } + template + bool readValBig(typename std::enable_if::value>::type* = 0) { + return readBool(); + } + + /** @brief Reads an atVec2f (8 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec2f readVec2f() { + simd_floats val; + readUBytesToBuf(val.data(), 8); + if (m_endian == Big) { + val[0] = utility::BigFloat(val[0]); + val[1] = utility::BigFloat(val[1]); + } else { + val[0] = utility::LittleFloat(val[0]); + val[1] = utility::LittleFloat(val[1]); + } + val[2] = 0.f; + val[3] = 0.f; + atVec2f s; + s.simd.copy_from(val); + return s; + } + template + atVec2f readVal(typename std::enable_if::value>::type* = 0) { + return readVec2f(); + } + + /** @brief Reads an atVec2f (8 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec2f readVec2fLittle() { + simd_floats val; + readUBytesToBuf(val.data(), 8); + val[0] = utility::LittleFloat(val[0]); + val[1] = utility::LittleFloat(val[1]); + val[2] = 0.f; + val[3] = 0.f; + atVec2f s; + s.simd.copy_from(val); + return s; + } + template + atVec2f readValLittle(typename std::enable_if::value>::type* = 0) { + return readVec2fLittle(); + } + + /** @brief Reads an atVec2f (8 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec2f readVec2fBig() { + simd_floats val; + readUBytesToBuf(val.data(), 8); + val[0] = utility::BigFloat(val[0]); + val[1] = utility::BigFloat(val[1]); + val[2] = 0.f; + val[3] = 0.f; + atVec2f s; + s.simd.copy_from(val); + return s; + } + template + atVec2f readValBig(typename std::enable_if::value>::type* = 0) { + return readVec2fBig(); + } + + /** @brief Reads an atVec3f (12 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec3f readVec3f() { + simd_floats val; + readUBytesToBuf(val.data(), 12); + if (m_endian == Big) { + val[0] = utility::BigFloat(val[0]); + val[1] = utility::BigFloat(val[1]); + val[2] = utility::BigFloat(val[2]); + } else { + val[0] = utility::LittleFloat(val[0]); + val[1] = utility::LittleFloat(val[1]); + val[2] = utility::LittleFloat(val[2]); + } + val[3] = 0.f; + atVec3f s; + s.simd.copy_from(val); + return s; + } + template + atVec3f readVal(typename std::enable_if::value>::type* = 0) { + return readVec3f(); + } + + /** @brief Reads an atVec3f (12 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec3f readVec3fLittle() { + simd_floats val; + readUBytesToBuf(val.data(), 12); + val[0] = utility::LittleFloat(val[0]); + val[1] = utility::LittleFloat(val[1]); + val[2] = utility::LittleFloat(val[2]); + val[3] = 0.f; + atVec3f s; + s.simd.copy_from(val); + return s; + } + template + atVec3f readValLittle(typename std::enable_if::value>::type* = 0) { + return readVec3fLittle(); + } + + /** @brief Reads an atVec3f (12 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec3f readVec3fBig() { + simd_floats val; + readUBytesToBuf(val.data(), 12); + val[0] = utility::BigFloat(val[0]); + val[1] = utility::BigFloat(val[1]); + val[2] = utility::BigFloat(val[2]); + val[3] = 0.f; + atVec3f s; + s.simd.copy_from(val); + return s; + } + template + atVec3f readValBig(typename std::enable_if::value>::type* = 0) { + return readVec3fBig(); + } + + /** @brief Reads an atVec4f (16 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec4f readVec4f() { + simd_floats val; + readUBytesToBuf(val.data(), 16); + if (m_endian == Big) { + val[0] = utility::BigFloat(val[0]); + val[1] = utility::BigFloat(val[1]); + val[2] = utility::BigFloat(val[2]); + val[3] = utility::BigFloat(val[3]); + } else { + val[0] = utility::LittleFloat(val[0]); + val[1] = utility::LittleFloat(val[1]); + val[2] = utility::LittleFloat(val[2]); + val[3] = utility::LittleFloat(val[3]); + } + atVec4f s; + s.simd.copy_from(val); + return s; + } + template + atVec4f readVal(typename std::enable_if::value>::type* = 0) { + return readVec4f(); + } + + /** @brief Reads an atVec4f (16 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec4f readVec4fLittle() { + simd_floats val; + readUBytesToBuf(val.data(), 16); + val[0] = utility::LittleFloat(val[0]); + val[1] = utility::LittleFloat(val[1]); + val[2] = utility::LittleFloat(val[2]); + val[3] = utility::LittleFloat(val[3]); + atVec4f s; + s.simd.copy_from(val); + return s; + } + template + atVec4f readValLittle(typename std::enable_if::value>::type* = 0) { + return readVec4fLittle(); + } + + /** @brief Reads an atVec4f (16 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec4f readVec4fBig() { + simd_floats val; + readUBytesToBuf(val.data(), 16); + val[0] = utility::BigFloat(val[0]); + val[1] = utility::BigFloat(val[1]); + val[2] = utility::BigFloat(val[2]); + val[3] = utility::BigFloat(val[3]); + atVec4f s; + s.simd.copy_from(val); + return s; + } + template + atVec4f readValBig(typename std::enable_if::value>::type* = 0) { + return readVec4fBig(); + } + + /** @brief Reads an atVec2d (16 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec2d readVec2d() { + simd_doubles val; + readUBytesToBuf(val.data(), 16); + if (m_endian == Big) { + val[0] = utility::BigDouble(val[0]); + val[1] = utility::BigDouble(val[1]); + } else { + val[0] = utility::LittleDouble(val[0]); + val[1] = utility::LittleDouble(val[1]); + } + val[2] = 0.0; + val[3] = 0.0; + atVec2d s; + s.simd.copy_from(val); + return s; + } + template + atVec2d readVal(typename std::enable_if::value>::type* = 0) { + return readVec2d(); + } + + /** @brief Reads an atVec2d (16 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec2d readVec2dLittle() { + simd_doubles val; + readUBytesToBuf(val.data(), 16); + val[0] = utility::LittleDouble(val[0]); + val[1] = utility::LittleDouble(val[1]); + val[2] = 0.0; + val[3] = 0.0; + atVec2d s; + s.simd.copy_from(val); + return s; + } + template + atVec2d readValLittle(typename std::enable_if::value>::type* = 0) { + return readVec2dLittle(); + } + + /** @brief Reads an atVec2d (16 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec2d readVec2dBig() { + simd_doubles val; + readUBytesToBuf(val.data(), 16); + val[0] = utility::BigDouble(val[0]); + val[1] = utility::BigDouble(val[1]); + val[2] = 0.0; + val[3] = 0.0; + atVec2d s; + s.simd.copy_from(val); + return s; + } + template + atVec2d readValBig(typename std::enable_if::value>::type* = 0) { + return readVec2dBig(); + } + + /** @brief Reads an atVec3d (24 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec3d readVec3d() { + simd_doubles val; + readUBytesToBuf(val.data(), 24); + if (m_endian == Big) { + val[0] = utility::BigDouble(val[0]); + val[1] = utility::BigDouble(val[1]); + val[2] = utility::BigDouble(val[2]); + } else { + val[0] = utility::LittleDouble(val[0]); + val[1] = utility::LittleDouble(val[1]); + val[2] = utility::LittleDouble(val[2]); + } + val[3] = 0.0; + atVec3d s; + s.simd.copy_from(val); + return s; + } + template + atVec3d readVal(typename std::enable_if::value>::type* = 0) { + return readVec3d(); + } + + /** @brief Reads an atVec3d (24 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec3d readVec3dLittle() { + simd_doubles val; + readUBytesToBuf(val.data(), 24); + val[0] = utility::LittleDouble(val[0]); + val[1] = utility::LittleDouble(val[1]); + val[2] = utility::LittleDouble(val[2]); + val[3] = 0.0; + atVec3d s; + s.simd.copy_from(val); + return s; + } + template + atVec3d readValLittle(typename std::enable_if::value>::type* = 0) { + return readVec3dLittle(); + } + + /** @brief Reads an atVec3d (24 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec3d readVec3dBig() { + simd_doubles val; + readUBytesToBuf(val.data(), 24); + val[0] = utility::BigDouble(val[0]); + val[1] = utility::BigDouble(val[1]); + val[2] = utility::BigDouble(val[2]); + val[3] = 0.0; + atVec3d s; + s.simd.copy_from(val); + return s; + } + template + atVec3d readValBig(typename std::enable_if::value>::type* = 0) { + return readVec3dBig(); + } + + /** @brief Reads an atVec4d (32 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec4d readVec4d() { + simd_doubles val; + readUBytesToBuf(val.data(), 32); + if (m_endian == Big) { + val[0] = utility::BigDouble(val[0]); + val[1] = utility::BigDouble(val[1]); + val[2] = utility::BigDouble(val[2]); + val[3] = utility::BigDouble(val[3]); + } else { + val[0] = utility::LittleDouble(val[0]); + val[1] = utility::LittleDouble(val[1]); + val[2] = utility::LittleDouble(val[2]); + val[3] = utility::LittleDouble(val[3]); + } + atVec4d s; + s.simd.copy_from(val); + return s; + } + template + atVec4d readVal(typename std::enable_if::value>::type* = 0) { + return readVec4d(); + } + + /** @brief Reads an atVec4d (32 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec4d readVec4dLittle() { + simd_doubles val; + readUBytesToBuf(val.data(), 32); + val[0] = utility::LittleDouble(val[0]); + val[1] = utility::LittleDouble(val[1]); + val[2] = utility::LittleDouble(val[2]); + val[3] = utility::LittleDouble(val[3]); + atVec4d s; + s.simd.copy_from(val); + return s; + } + template + atVec4d readValLittle(typename std::enable_if::value>::type* = 0) { + return readVec4dLittle(); + } + + /** @brief Reads an atVec4d (32 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + atVec4d readVec4dBig() { + simd_doubles val; + readUBytesToBuf(val.data(), 32); + val[0] = utility::BigDouble(val[0]); + val[1] = utility::BigDouble(val[1]); + val[2] = utility::BigDouble(val[2]); + val[3] = utility::BigDouble(val[3]); + atVec4d s; + s.simd.copy_from(val); + return s; + } + template + atVec4d readValBig(typename std::enable_if::value>::type* = 0) { + return readVec4dBig(); + } + + /** @brief Reads a string and advances the position in the file + * + * @param fixedLen If non-negative, this is a fixed-length string read + * @return The read string + */ + std::string readString(atInt32 fixedLen = -1, bool doSeek = true) { + if (fixedLen == 0) + return std::string(); + std::string ret; + atUint8 chr = readByte(); + + atInt32 i; + for (i = 1; chr != 0; ++i) { + ret += chr; + + if (fixedLen > 0 && i >= fixedLen) + break; + + chr = readByte(); } - /** @brief Reads a byte at the current position and advances the current position. - * - * @return The buffer at the current position from the given length. - */ - std::unique_ptr readUBytes(atUint64 length) - { - atUint8* buf = new atUint8[length]; - readUBytesToBuf(buf, length); - return std::unique_ptr(buf); + if (doSeek && fixedLen > 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + std::string readVal(typename std::enable_if::value>::type* = 0) { + return readString(); + } + + /** @brief Reads a wstring and advances the position in the file + * + * @param fixedLen If non-negative, this is a fixed-length string read + * @return The read wstring + */ + std::wstring readWString(atInt32 fixedLen = -1, bool doSeek = true) { + if (fixedLen == 0) + return std::wstring(); + + std::wstring ret; + atUint16 chr = readUint16(); + + atInt32 i; + for (i = 1; chr != 0; ++i) { + ret += chr; + + if (fixedLen > 0 && i >= fixedLen) + break; + + chr = readUint16(); } - /** @brief Attempts to read a fixed length of data into a pre-allocated buffer. - * @param buf The buffer to read into - * @param len The length of the buffer - * @return How much data was actually read, useful for detecting read errors. - */ - atUint64 readBytesToBuf(void* buf, atUint64 len) {return readUBytesToBuf(buf, len);} - - - /** @brief Attempts to read a fixed length of data into a pre-allocated buffer, this function is client defined - * and must be implemented. - * @param buf The buffer to read into - * @param len The length of the buffer - * @return How much data was actually read, useful for detecting read errors. - */ - virtual atUint64 readUBytesToBuf(void* buf, atUint64 len)=0; - - /** @brief Reads a Int16 and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt16 readInt16() - { - atInt16 val; - readUBytesToBuf(&val, 2); - return m_endian == Big ? utility::BigInt16(val) : utility::LittleInt16(val); - } - template - atInt16 readVal(typename std::enable_if::value>::type* = 0) - {return readInt16();} - - /** @brief Reads a Int16 and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt16 readInt16Little() - { - atInt16 val; - readUBytesToBuf(&val, 2); - return utility::LittleInt16(val); - } - template - atInt16 readValLittle(typename std::enable_if::value>::type* = 0) - {return readInt16Little();} - - /** @brief Reads a Int16 and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt16 readInt16Big() - { - atInt16 val; - readUBytesToBuf(&val, 2); - return utility::BigInt16(val); - } - template - atInt16 readValBig(typename std::enable_if::value>::type* = 0) - {return readInt16Big();} - - /** @brief Reads a Uint16 and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint16 readUint16() - {return readInt16();} - template - atUint16 readVal(typename std::enable_if::value>::type* = 0) - {return readUint16();} - - /** @brief Reads a Uint16 and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint16 readUint16Little() - { - atUint16 val; - readUBytesToBuf(&val, 2); - return utility::LittleUint16(val); - } - template - atUint16 readValLittle(typename std::enable_if::value>::type* = 0) - {return readUint16Little();} - - /** @brief Reads a Uint16 and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint16 readUint16Big() - { - atUint16 val; - readUBytesToBuf(&val, 2); - return utility::BigUint16(val); - } - template - atUint16 readValBig(typename std::enable_if::value>::type* = 0) - {return readUint16Big();} - - /** @brief Reads a Int32 and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt32 readInt32() - { - atInt32 val; - readUBytesToBuf(&val, 4); - return m_endian == Big ? utility::BigInt32(val) : utility::LittleInt32(val); - } - template - atInt32 readVal(typename std::enable_if::value>::type* = 0) - {return readInt32();} - - /** @brief Reads a Int32 and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt32 readInt32Little() - { - atInt32 val; - readUBytesToBuf(&val, 4); - return utility::LittleInt32(val); - } - template - atInt32 readValLittle(typename std::enable_if::value>::type* = 0) - {return readInt32Little();} - - /** @brief Reads a Int32 and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt32 readInt32Big() - { - atInt32 val; - readUBytesToBuf(&val, 4); - return utility::BigInt32(val); - } - template - atInt32 readValBig(typename std::enable_if::value>::type* = 0) - {return readInt32Big();} - - /** @brief Reads a Uint32 and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint32 readUint32() - {return readInt32();} - template - atUint32 readVal(typename std::enable_if::value>::type* = 0) - {return readUint32();} - - /** @brief Reads a Uint32 and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint32 readUint32Little() - { - atUint32 val; - readUBytesToBuf(&val, 4); - return utility::LittleUint32(val); - } - template - atInt32 readValLittle(typename std::enable_if::value>::type* = 0) - {return readUint32Little();} - - /** @brief Reads a Uint32 and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint32 readUint32Big() - { - atUint32 val; - readUBytesToBuf(&val, 4); - return utility::BigUint32(val); - } - template - atUint32 readValBig(typename std::enable_if::value>::type* = 0) - {return readUint32Big();} - - /** @brief Reads a Int64 and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt64 readInt64() - { - atInt64 val; - readUBytesToBuf(&val, 8); - return m_endian == Big ? utility::BigInt64(val) : utility::LittleInt64(val); - } - template - atInt64 readVal(typename std::enable_if::value>::type* = 0) - {return readInt64();} - - /** @brief Reads a Int64 and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt64 readInt64Little() - { - atInt64 val; - readUBytesToBuf(&val, 8); - return utility::LittleInt64(val); - } - template - atInt64 readValLittle(typename std::enable_if::value>::type* = 0) - {return readInt64Little();} - - /** @brief Reads a Int64 and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atInt64 readInt64Big() - { - atInt64 val; - readUBytesToBuf(&val, 8); - return utility::BigInt64(val); - } - template - atInt64 readValBig(typename std::enable_if::value>::type* = 0) - {return readInt64Big();} - - /** @brief Reads a Uint64 and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint64 readUint64() - {return readInt64();} - template - atUint64 readVal(typename std::enable_if::value>::type* = 0) - {return readUint64();} - - /** @brief Reads a Uint64 and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint64 readUint64Little() - { - atUint64 val; - readUBytesToBuf(&val, 8); - return utility::LittleUint64(val); - } - template - atUint64 readValLittle(typename std::enable_if::value>::type* = 0) - {return readUint64Little();} - - /** @brief Reads a Uint64 and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atUint64 readUint64Big() - { - atUint64 val; - readUBytesToBuf(&val, 8); - return utility::BigUint64(val); - } - template - atUint64 readValBig(typename std::enable_if::value>::type* = 0) - {return readUint64Big();} - - /** @brief Reads a float and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - float readFloat() - { - float val; - readUBytesToBuf(&val, 4); - return m_endian == Big ? utility::BigFloat(val) : utility::LittleFloat(val); - } - template - float readVal(typename std::enable_if::value>::type* = 0) - {return readFloat();} - - /** @brief Reads a float and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - float readFloatLittle() - { - float val; - readUBytesToBuf(&val, 4); - return utility::LittleFloat(val); - } - template - float readValLittle(typename std::enable_if::value>::type* = 0) - {return readFloatLittle();} - - /** @brief Reads a float and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - float readFloatBig() - { - float val; - readUBytesToBuf(&val, 4); - return utility::BigFloat(val); - } - template - float readValBig(typename std::enable_if::value>::type* = 0) - {return readFloatBig();} - - /** @brief Reads a double and swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - double readDouble() - { - double val; - readUBytesToBuf(&val, 8); - return m_endian == Big ? utility::BigDouble(val) : utility::LittleDouble(val); - } - template - double readVal(typename std::enable_if::value>::type* = 0) - {return readDouble();} - - /** @brief Reads a double and swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - double readDoubleLittle() - { - double val; - readUBytesToBuf(&val, 8); - return utility::LittleDouble(val); - } - template - double readValLittle(typename std::enable_if::value>::type* = 0) - {return readDoubleLittle();} - - /** @brief Reads a double and swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - double readDoubleBig() - { - double val; - readUBytesToBuf(&val, 8); - return utility::BigDouble(val); - } - template - double readValBig(typename std::enable_if::value>::type* = 0) - {return readDoubleBig();} - - /** @brief Reads a bool and advances the current position - * - * @return The value at the current address - */ - bool readBool() - { - atUint8 val; - readUBytesToBuf(&val, 1); - return val != 0; - } - template - bool readVal(typename std::enable_if::value>::type* = 0) - {return readBool();} - template - bool readValLittle(typename std::enable_if::value>::type* = 0) - {return readBool();} - template - bool readValBig(typename std::enable_if::value>::type* = 0) - {return readBool();} - - /** @brief Reads an atVec2f (8 bytes), swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec2f readVec2f() - { - simd_floats val; - readUBytesToBuf(val.data(), 8); - if (m_endian == Big) - { - val[0] = utility::BigFloat(val[0]); - val[1] = utility::BigFloat(val[1]); - } - else - { - val[0] = utility::LittleFloat(val[0]); - val[1] = utility::LittleFloat(val[1]); - } - val[2] = 0.f; - val[3] = 0.f; - atVec2f s; - s.simd.copy_from(val); - return s; - } - template - atVec2f readVal(typename std::enable_if::value>::type* = 0) - {return readVec2f();} - - /** @brief Reads an atVec2f (8 bytes), swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec2f readVec2fLittle() - { - simd_floats val; - readUBytesToBuf(val.data(), 8); - val[0] = utility::LittleFloat(val[0]); - val[1] = utility::LittleFloat(val[1]); - val[2] = 0.f; - val[3] = 0.f; - atVec2f s; - s.simd.copy_from(val); - return s; - } - template - atVec2f readValLittle(typename std::enable_if::value>::type* = 0) - {return readVec2fLittle();} - - /** @brief Reads an atVec2f (8 bytes), swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec2f readVec2fBig() - { - simd_floats val; - readUBytesToBuf(val.data(), 8); - val[0] = utility::BigFloat(val[0]); - val[1] = utility::BigFloat(val[1]); - val[2] = 0.f; - val[3] = 0.f; - atVec2f s; - s.simd.copy_from(val); - return s; - } - template - atVec2f readValBig(typename std::enable_if::value>::type* = 0) - {return readVec2fBig();} - - /** @brief Reads an atVec3f (12 bytes), swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec3f readVec3f() - { - simd_floats val; - readUBytesToBuf(val.data(), 12); - if (m_endian == Big) - { - val[0] = utility::BigFloat(val[0]); - val[1] = utility::BigFloat(val[1]); - val[2] = utility::BigFloat(val[2]); - } - else - { - val[0] = utility::LittleFloat(val[0]); - val[1] = utility::LittleFloat(val[1]); - val[2] = utility::LittleFloat(val[2]); - } - val[3] = 0.f; - atVec3f s; - s.simd.copy_from(val); - return s; - } - template - atVec3f readVal(typename std::enable_if::value>::type* = 0) - {return readVec3f();} - - /** @brief Reads an atVec3f (12 bytes), swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec3f readVec3fLittle() - { - simd_floats val; - readUBytesToBuf(val.data(), 12); - val[0] = utility::LittleFloat(val[0]); - val[1] = utility::LittleFloat(val[1]); - val[2] = utility::LittleFloat(val[2]); - val[3] = 0.f; - atVec3f s; - s.simd.copy_from(val); - return s; - } - template - atVec3f readValLittle(typename std::enable_if::value>::type* = 0) - {return readVec3fLittle();} - - /** @brief Reads an atVec3f (12 bytes), swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec3f readVec3fBig() - { - simd_floats val; - readUBytesToBuf(val.data(), 12); - val[0] = utility::BigFloat(val[0]); - val[1] = utility::BigFloat(val[1]); - val[2] = utility::BigFloat(val[2]); - val[3] = 0.f; - atVec3f s; - s.simd.copy_from(val); - return s; - } - template - atVec3f readValBig(typename std::enable_if::value>::type* = 0) - {return readVec3fBig();} - - /** @brief Reads an atVec4f (16 bytes), swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec4f readVec4f() - { - simd_floats val; - readUBytesToBuf(val.data(), 16); - if (m_endian == Big) - { - val[0] = utility::BigFloat(val[0]); - val[1] = utility::BigFloat(val[1]); - val[2] = utility::BigFloat(val[2]); - val[3] = utility::BigFloat(val[3]); - } - else - { - val[0] = utility::LittleFloat(val[0]); - val[1] = utility::LittleFloat(val[1]); - val[2] = utility::LittleFloat(val[2]); - val[3] = utility::LittleFloat(val[3]); - } - atVec4f s; - s.simd.copy_from(val); - return s; - } - template - atVec4f readVal(typename std::enable_if::value>::type* = 0) - {return readVec4f();} - - /** @brief Reads an atVec4f (16 bytes), swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec4f readVec4fLittle() - { - simd_floats val; - readUBytesToBuf(val.data(), 16); - val[0] = utility::LittleFloat(val[0]); - val[1] = utility::LittleFloat(val[1]); - val[2] = utility::LittleFloat(val[2]); - val[3] = utility::LittleFloat(val[3]); - atVec4f s; - s.simd.copy_from(val); - return s; - } - template - atVec4f readValLittle(typename std::enable_if::value>::type* = 0) - {return readVec4fLittle();} - - /** @brief Reads an atVec4f (16 bytes), swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec4f readVec4fBig() - { - simd_floats val; - readUBytesToBuf(val.data(), 16); - val[0] = utility::BigFloat(val[0]); - val[1] = utility::BigFloat(val[1]); - val[2] = utility::BigFloat(val[2]); - val[3] = utility::BigFloat(val[3]); - atVec4f s; - s.simd.copy_from(val); - return s; - } - template - atVec4f readValBig(typename std::enable_if::value>::type* = 0) - {return readVec4fBig();} - - /** @brief Reads an atVec2d (16 bytes), swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec2d readVec2d() - { - simd_doubles val; - readUBytesToBuf(val.data(), 16); - if (m_endian == Big) - { - val[0] = utility::BigDouble(val[0]); - val[1] = utility::BigDouble(val[1]); - } - else - { - val[0] = utility::LittleDouble(val[0]); - val[1] = utility::LittleDouble(val[1]); - } - val[2] = 0.0; - val[3] = 0.0; - atVec2d s; - s.simd.copy_from(val); - return s; - } - template - atVec2d readVal(typename std::enable_if::value>::type* = 0) - {return readVec2d();} - - /** @brief Reads an atVec2d (16 bytes), swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec2d readVec2dLittle() - { - simd_doubles val; - readUBytesToBuf(val.data(), 16); - val[0] = utility::LittleDouble(val[0]); - val[1] = utility::LittleDouble(val[1]); - val[2] = 0.0; - val[3] = 0.0; - atVec2d s; - s.simd.copy_from(val); - return s; - } - template - atVec2d readValLittle(typename std::enable_if::value>::type* = 0) - {return readVec2dLittle();} - - /** @brief Reads an atVec2d (16 bytes), swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec2d readVec2dBig() - { - simd_doubles val; - readUBytesToBuf(val.data(), 16); - val[0] = utility::BigDouble(val[0]); - val[1] = utility::BigDouble(val[1]); - val[2] = 0.0; - val[3] = 0.0; - atVec2d s; - s.simd.copy_from(val); - return s; - } - template - atVec2d readValBig(typename std::enable_if::value>::type* = 0) - {return readVec2dBig();} - - /** @brief Reads an atVec3d (24 bytes), swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec3d readVec3d() - { - simd_doubles val; - readUBytesToBuf(val.data(), 24); - if (m_endian == Big) - { - val[0] = utility::BigDouble(val[0]); - val[1] = utility::BigDouble(val[1]); - val[2] = utility::BigDouble(val[2]); - } - else - { - val[0] = utility::LittleDouble(val[0]); - val[1] = utility::LittleDouble(val[1]); - val[2] = utility::LittleDouble(val[2]); - } - val[3] = 0.0; - atVec3d s; - s.simd.copy_from(val); - return s; - } - template - atVec3d readVal(typename std::enable_if::value>::type* = 0) - {return readVec3d();} - - /** @brief Reads an atVec3d (24 bytes), swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec3d readVec3dLittle() - { - simd_doubles val; - readUBytesToBuf(val.data(), 24); - val[0] = utility::LittleDouble(val[0]); - val[1] = utility::LittleDouble(val[1]); - val[2] = utility::LittleDouble(val[2]); - val[3] = 0.0; - atVec3d s; - s.simd.copy_from(val); - return s; - } - template - atVec3d readValLittle(typename std::enable_if::value>::type* = 0) - {return readVec3dLittle();} - - /** @brief Reads an atVec3d (24 bytes), swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec3d readVec3dBig() - { - simd_doubles val; - readUBytesToBuf(val.data(), 24); - val[0] = utility::BigDouble(val[0]); - val[1] = utility::BigDouble(val[1]); - val[2] = utility::BigDouble(val[2]); - val[3] = 0.0; - atVec3d s; - s.simd.copy_from(val); - return s; - } - template - atVec3d readValBig(typename std::enable_if::value>::type* = 0) - {return readVec3dBig();} - - /** @brief Reads an atVec4d (32 bytes), swaps to endianness specified by setEndian depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec4d readVec4d() - { - simd_doubles val; - readUBytesToBuf(val.data(), 32); - if (m_endian == Big) - { - val[0] = utility::BigDouble(val[0]); - val[1] = utility::BigDouble(val[1]); - val[2] = utility::BigDouble(val[2]); - val[3] = utility::BigDouble(val[3]); - } - else - { - val[0] = utility::LittleDouble(val[0]); - val[1] = utility::LittleDouble(val[1]); - val[2] = utility::LittleDouble(val[2]); - val[3] = utility::LittleDouble(val[3]); - } - atVec4d s; - s.simd.copy_from(val); - return s; - } - template - atVec4d readVal(typename std::enable_if::value>::type* = 0) - {return readVec4d();} - - /** @brief Reads an atVec4d (32 bytes), swaps against little endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec4d readVec4dLittle() - { - simd_doubles val; - readUBytesToBuf(val.data(), 32); - val[0] = utility::LittleDouble(val[0]); - val[1] = utility::LittleDouble(val[1]); - val[2] = utility::LittleDouble(val[2]); - val[3] = utility::LittleDouble(val[3]); - atVec4d s; - s.simd.copy_from(val); - return s; - } - template - atVec4d readValLittle(typename std::enable_if::value>::type* = 0) - {return readVec4dLittle();} - - /** @brief Reads an atVec4d (32 bytes), swaps against big endianness depending on platform - * and advances the current position - * - * @return The value at the current address - */ - atVec4d readVec4dBig() - { - simd_doubles val; - readUBytesToBuf(val.data(), 32); - val[0] = utility::BigDouble(val[0]); - val[1] = utility::BigDouble(val[1]); - val[2] = utility::BigDouble(val[2]); - val[3] = utility::BigDouble(val[3]); - atVec4d s; - s.simd.copy_from(val); - return s; - } - template - atVec4d readValBig(typename std::enable_if::value>::type* = 0) - {return readVec4dBig();} - - /** @brief Reads a string and advances the position in the file - * - * @param fixedLen If non-negative, this is a fixed-length string read - * @return The read string - */ - std::string readString(atInt32 fixedLen = -1, bool doSeek=true) - { - if (fixedLen == 0) - return std::string(); - std::string ret; - atUint8 chr = readByte(); - - atInt32 i; - for (i = 1 ; chr != 0 ; ++i) - { - ret += chr; - - if (fixedLen > 0 && i >= fixedLen) - break; - - chr = readByte(); - } - - if (doSeek && fixedLen > 0 && i < fixedLen) - seek(fixedLen - i); - - return ret; - } - template - std::string readVal(typename std::enable_if::value>::type* = 0) - {return readString();} - - /** @brief Reads a wstring and advances the position in the file - * - * @param fixedLen If non-negative, this is a fixed-length string read - * @return The read wstring - */ - std::wstring readWString(atInt32 fixedLen = -1, bool doSeek=true) - { - if (fixedLen == 0) - return std::wstring(); - - std::wstring ret; - atUint16 chr = readUint16(); - - atInt32 i; - for (i = 1 ; chr != 0 ; ++i) - { - ret += chr; - - if (fixedLen > 0 && i >= fixedLen) - break; - - chr = readUint16(); - } - - if (doSeek && fixedLen > 0 && i < fixedLen) - seek(fixedLen - i); - - return ret; - } - template - std::wstring readVal(typename std::enable_if::value>::type* = 0) - {return readWString();} - - /** @brief Reads a wstring assuming little-endian characters - * and advances the position in the file - * - * @param fixedLen If non-negative, this is a fixed-length string read - * @return The read wstring - */ - std::wstring readWStringLittle(atInt32 fixedLen = -1, bool doSeek=true) - { - if (fixedLen == 0) - return std::wstring(); - - 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 (doSeek && fixedLen > 0 && i < fixedLen) - seek(fixedLen - i); - - return ret; - } - template - std::wstring readValLittle(typename std::enable_if::value>::type* = 0) - {return readWStringLittle();} - - /** @brief Reads a wstring assuming big-endian characters - * and advances the position in the file - * - * @param fixedLen If non-negative, this is a fixed-length string read - * @return The read wstring - */ - std::wstring readWStringBig(atInt32 fixedLen = -1, bool doSeek = true) - { - if (fixedLen == 0) - return std::wstring(); - 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 (doSeek && fixedLen > 0 && i < fixedLen) - seek(fixedLen - i); - - return ret; - } - template - std::wstring readValBig(typename std::enable_if::value>::type* = 0) - {return readWStringBig();} - - /** @brief Reads a u16string assuming big-endian characters - * and advances the position in the file - * - * @param fixedLen If non-negative, this is a fixed-length string read - * @return The read wstring - */ - std::u16string readU16StringBig(atInt32 fixedLen = -1, bool doSeek = true) - { - if (fixedLen == 0) - return std::u16string(); - std::u16string ret; - char16_t chr = readUint16Big(); - - atInt32 i; - for (i = 1 ; chr != 0 ; ++i) - { - ret += chr; - - if (fixedLen > 0 && i >= fixedLen) - break; - - chr = readUint16Big(); - } - - if (doSeek && fixedLen > 0 && i < fixedLen) - seek(fixedLen - i); - - return ret; - } - template - std::u16string readValBig(typename std::enable_if::value>::type* = 0) - {return readU16StringBig();} - - /** @brief Reads a u32string assuming big-endian characters - * and advances the position in the file - * - * @param fixedLen If non-negative, this is a fixed-length string read - * @return The read wstring - */ - std::u32string readU32StringBig(atInt32 fixedLen = -1, bool doSeek = true) - { - if (fixedLen == 0) - return std::u32string(); - std::u32string ret; - char32_t chr = readUint32Big(); - - atInt32 i; - for (i = 1 ; chr != 0 ; ++i) - { - ret += chr; - - if (fixedLen > 0 && i >= fixedLen) - break; - - chr = readUint32Big(); - } - - if (doSeek && fixedLen > 0 && i < fixedLen) - seek(fixedLen - i); - - return ret; - } - template - std::u32string readValBig(typename std::enable_if::value>::type* = 0) - {return readU32StringBig();} - - /** @brief Performs automatic std::vector enumeration reads using numeric type T - * - * @param vector The std::vector to clear and populate using read data - * @param count The number of elements to read into vector - * - * Endianness is set with setEndian - */ - template - void enumerate(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()); + if (doSeek && fixedLen > 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + std::wstring readVal(typename std::enable_if::value>::type* = 0) { + return readWString(); + } + + /** @brief Reads a wstring assuming little-endian characters + * and advances the position in the file + * + * @param fixedLen If non-negative, this is a fixed-length string read + * @return The read wstring + */ + std::wstring readWStringLittle(atInt32 fixedLen = -1, bool doSeek = true) { + if (fixedLen == 0) + return std::wstring(); + + std::wstring ret; + atUint16 chr = readUint16Little(); + + atInt32 i; + for (i = 1; chr != 0; ++i) { + ret += chr; + + if (fixedLen > 0 && i >= fixedLen) + break; + + chr = readUint16Little(); } - /** @brief Performs automatic std::vector enumeration reads using numeric type T - * - * @param vector The std::vector to clear and populate using read data - * @param count The number of elements to read into vector - * - * Endianness is little - */ - 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()); + if (doSeek && fixedLen > 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + std::wstring readValLittle(typename std::enable_if::value>::type* = 0) { + return readWStringLittle(); + } + + /** @brief Reads a wstring assuming big-endian characters + * and advances the position in the file + * + * @param fixedLen If non-negative, this is a fixed-length string read + * @return The read wstring + */ + std::wstring readWStringBig(atInt32 fixedLen = -1, bool doSeek = true) { + if (fixedLen == 0) + return std::wstring(); + std::wstring ret; + atUint16 chr = readUint16Big(); + + atInt32 i; + for (i = 1; chr != 0; ++i) { + ret += chr; + + if (fixedLen > 0 && i >= fixedLen) + break; + + chr = readUint16Big(); } - /** @brief Performs automatic std::vector enumeration reads using numeric type T - * - * @param vector The std::vector to clear and populate using read data - * @param count The number of elements to read into vector - * - * Endianness is big - */ - 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()); + if (doSeek && fixedLen > 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + std::wstring readValBig(typename std::enable_if::value>::type* = 0) { + return readWStringBig(); + } + + /** @brief Reads a u16string assuming big-endian characters + * and advances the position in the file + * + * @param fixedLen If non-negative, this is a fixed-length string read + * @return The read wstring + */ + std::u16string readU16StringBig(atInt32 fixedLen = -1, bool doSeek = true) { + if (fixedLen == 0) + return std::u16string(); + std::u16string ret; + char16_t chr = readUint16Big(); + + atInt32 i; + for (i = 1; chr != 0; ++i) { + ret += chr; + + if (fixedLen > 0 && i >= fixedLen) + break; + + chr = readUint16Big(); } - /** @brief Performs automatic std::vector enumeration reads using non-numeric type T - * - * @param vector The std::vector to clear and populate using read data - * @param count The number of elements to read into vector - */ - template - void enumerate(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 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + std::u16string readValBig(typename std::enable_if::value>::type* = 0) { + return readU16StringBig(); + } + + /** @brief Reads a u32string assuming big-endian characters + * and advances the position in the file + * + * @param fixedLen If non-negative, this is a fixed-length string read + * @return The read wstring + */ + std::u32string readU32StringBig(atInt32 fixedLen = -1, bool doSeek = true) { + if (fixedLen == 0) + return std::u32string(); + std::u32string ret; + char32_t chr = readUint32Big(); + + atInt32 i; + for (i = 1; chr != 0; ++i) { + ret += chr; + + if (fixedLen > 0 && i >= fixedLen) + break; + + chr = readUint32Big(); } - /** @brief Performs lambda-assisted std::vector enumeration reads using type T - * - * @param vector The std::vector to clear and populate using read data - * @param count The number of elements to read into vector - * @param readf Function (e.g. a lambda) that reads *one* element and - * assigns the value through the second argument - */ - template - void enumerate(std::vector& vector, size_t count, std::function readf) - { - vector.clear(); - vector.reserve(count); - for (size_t i=0 ; i 0 && i < fixedLen) + seek(fixedLen - i); + + return ret; + } + template + std::u32string readValBig(typename std::enable_if::value>::type* = 0) { + return readU32StringBig(); + } + + /** @brief Performs automatic std::vector enumeration reads using numeric type T + * + * @param vector The std::vector to clear and populate using read data + * @param count The number of elements to read into vector + * + * Endianness is set with setEndian + */ + template + void + enumerate(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 < count; ++i) + vector.push_back(readVal()); + } + + /** @brief Performs automatic std::vector enumeration reads using numeric type T + * + * @param vector The std::vector to clear and populate using read data + * @param count The number of elements to read into vector + * + * Endianness is little + */ + 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 < count; ++i) + vector.push_back(readValLittle()); + } + + /** @brief Performs automatic std::vector enumeration reads using numeric type T + * + * @param vector The std::vector to clear and populate using read data + * @param count The number of elements to read into vector + * + * Endianness is big + */ + 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 < count; ++i) + vector.push_back(readValBig()); + } + + /** @brief Performs automatic std::vector enumeration reads using non-numeric type T + * + * @param vector The std::vector to clear and populate using read data + * @param count The number of elements to read into vector + */ + template + void + enumerate(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 < count; ++i) { + vector.emplace_back(); + vector.back().read(*this); } + } + + /** @brief Performs lambda-assisted std::vector enumeration reads using type T + * + * @param vector The std::vector to clear and populate using read data + * @param count The number of elements to read into vector + * @param readf Function (e.g. a lambda) that reads *one* element and + * assigns the value through the second argument + */ + template + void enumerate(std::vector& vector, size_t count, std::function readf) { + vector.clear(); + vector.reserve(count); + for (size_t i = 0; i < count; ++i) { + vector.emplace_back(); + readf(*this, vector.back()); + } + } }; template -IStreamReader& operator>>(IStreamReader& lhs, T& rhs) -{ - rhs = lhs.readVal(); - return lhs; +IStreamReader& operator>>(IStreamReader& lhs, T& rhs) { + rhs = lhs.readVal(); + return lhs; } -} - +} // namespace athena::io diff --git a/include/athena/IStreamWriter.hpp b/include/athena/IStreamWriter.hpp index 54e8a38..f10dd68 100644 --- a/include/athena/IStreamWriter.hpp +++ b/include/athena/IStreamWriter.hpp @@ -6,1174 +6,1042 @@ #include #include -namespace athena::io -{ -class IStreamWriter : public IStream -{ +namespace athena::io { +class IStreamWriter : public IStream { public: - virtual ~IStreamWriter() = default; + virtual ~IStreamWriter() = default; - /** @brief Sets the buffers position relative to the specified position.
- * It seeks relative to the current position by default. - * @param position where in the buffer to seek - * @param origin The location to seek relative to - */ - virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)=0; + /** @brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * @param position where in the buffer to seek + * @param origin The location to seek relative to + */ + virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current) = 0; - /** @brief Sets the buffers position relative to the next 32-byte aligned position.
- */ - void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);} + /** @brief Sets the buffers position relative to the next 32-byte aligned position.
+ */ + void seekAlign32() { seek(ROUND_UP_32(position()), SeekOrigin::Begin); } - /** @brief Writes zero up to specified absolute offset.
- */ - void writeZeroTo(atInt64 pos) - { - atInt64 delta = pos - position(); - if (delta <= 0) + /** @brief Writes zero up to specified absolute offset.
+ */ + void writeZeroTo(atInt64 pos) { + atInt64 delta = pos - position(); + if (delta <= 0) + return; + for (atInt64 i = 0; i < delta; ++i) + writeUByte(0); + } + + /** @brief Returns whether or not the stream is at the end. + * + * @return True if at end; False otherwise. + */ + bool atEnd() const { return position() >= length(); } + + /** @brief Returns the current position in the stream. + * + * @return The current position in the stream. + */ + virtual atUint64 position() const = 0; + + /** @brief Returns whether or not the stream is at the end. + * + * @return True if at end; False otherwise. + */ + virtual atUint64 length() const = 0; + + /** @brief Writes a byte at the current position and advances the position by one byte. + * @param val The value to write + */ + void writeUByte(atUint8 val) { writeUBytes(&val, 1); } + void writeVal(atUint8 val) { writeUByte(val); } + void writeValLittle(atUint8 val) { writeUByte(val); } + void writeValBig(atUint8 val) { writeUByte(val); } + + /** @brief Writes a byte at the current position and advances the position by one byte. + * @param val The value to write + */ + void writeByte(atInt8 val) { writeUByte(val); } + void writeVal(atInt8 val) { writeByte(val); } + void writeValLittle(atInt8 val) { writeByte(val); } + void writeValBig(atInt8 val) { writeByte(val); } + + /** @brief Writes the given buffer with the specified length, buffers can be bigger than the length + * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * + * @param data The buffer to write + * @param length The amount to write + */ + virtual void writeUBytes(const atUint8* data, atUint64 len) = 0; + + /** @brief Writes the given buffer with the specified length, buffers can be bigger than the length + * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * + * @param data The buffer to write + * @param length The amount to write + */ + void writeBytes(const void* data, atUint64 len) { writeUBytes((atUint8*)data, len); } + + /** @brief Writes an Int16 to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param val The value to write to the buffer + */ + void writeInt16(atInt16 val) { + if (m_endian == Big) + utility::BigInt16(val); + else + utility::LittleInt16(val); + writeUBytes((atUint8*)&val, 2); + } + void writeVal(atInt16 val) { writeInt16(val); } + + /** @brief Writes an Int16 to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeInt16Little(atInt16 val) { + utility::LittleInt16(val); + writeUBytes((atUint8*)&val, 2); + } + void writeValLittle(atInt16 val) { writeInt16Little(val); } + + /** @brief Writes an Int16 to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeInt16Big(atInt16 val) { + utility::BigInt16(val); + writeUBytes((atUint8*)&val, 2); + } + void writeValBig(atInt16 val) { 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 + * + * @param val The value to write to the buffer + */ + void writeUint16(atUint16 val) { writeInt16(val); } + void writeVal(atUint16 val) { writeUint16(val); } + + /** @brief Writes an Uint16 to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform + * + * @param val The value to write to the buffer + */ + void writeUint16Little(atUint16 val) { writeInt16Little(val); } + void writeValLittle(atUint16 val) { writeUint16Little(val); } + + /** @brief Writes an Uint16 to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform + * + * @param val The value to write to the buffer + */ + void writeUint16Big(atUint16 val) { writeInt16Big(val); } + void writeValBig(atUint16 val) { 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. + * + * @param val The value to write to the buffer + */ + void writeInt32(atInt32 val) { + if (m_endian == Big) + utility::BigInt32(val); + else + utility::LittleInt32(val); + writeUBytes((atUint8*)&val, 4); + } + void writeVal(atInt32 val) { writeInt32(val); } + + /** @brief Writes an Int32 to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeInt32Little(atInt32 val) { + utility::LittleInt32(val); + writeUBytes((atUint8*)&val, 4); + } + void writeValLittle(atInt32 val) { writeInt32Little(val); } + + /** @brief Writes an Int32 to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeInt32Big(atInt32 val) { + utility::BigInt32(val); + writeUBytes((atUint8*)&val, 4); + } + void writeValBig(atInt32 val) { 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. + * + * @param val The value to write to the buffer + */ + void writeUint32(atUint32 val) { writeInt32(val); } + void writeVal(atUint32 val) { writeUint32(val); } + + /** @brief Writes an Uint32 to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeUint32Little(atUint32 val) { writeInt32Little(val); } + void writeValLittle(atUint32 val) { writeUint32Little(val); } + + /** @brief Writes an Uint32 to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeUint32Big(atUint32 val) { writeInt32Big(val); } + void writeValBig(atUint32 val) { 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. + * + * @param val The value to write to the buffer + */ + void writeInt64(atInt64 val) { + if (m_endian == Big) + utility::BigInt64(val); + else + utility::LittleInt64(val); + writeUBytes((atUint8*)&val, 8); + } + void writeVal(atInt64 val) { writeInt64(val); } + + /** @brief Writes an Int64 to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeInt64Little(atInt64 val) { + utility::LittleInt64(val); + writeUBytes((atUint8*)&val, 8); + } + void writeValLittle(atInt64 val) { writeInt64Little(val); } + + /** @brief Writes an Int64 to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeInt64Big(atInt64 val) { + utility::BigInt64(val); + writeUBytes((atUint8*)&val, 8); + } + void writeValBig(atInt64 val) { 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. + * + * @param val The value to write to the buffer + */ + void writeUint64(atUint64 val) { writeInt64(val); } + void writeVal(atUint64 val) { writeUint64(val); } + + /** @brief Writes an Uint64 to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeUint64Little(atUint64 val) { writeInt64Little(val); } + void writeValLittle(atUint64 val) { writeUint64Little(val); } + + /** @brief Writes an Uint64 to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeUint64Big(atUint64 val) { writeInt64Big(val); } + void writeValBig(atUint64 val) { 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. + * + * @param val The value to write to the buffer + */ + void writeFloat(float val) { + if (m_endian == Big) + val = utility::BigFloat(val); + else + val = utility::LittleFloat(val); + writeUBytes((atUint8*)&val, 4); + } + void writeVal(float val) { writeFloat(val); } + + /** @brief Writes an float to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeFloatLittle(float val) { + utility::LittleFloat(val); + writeUBytes((atUint8*)&val, 4); + } + void writeValLittle(float val) { writeFloatLittle(val); } + + /** @brief Writes an float to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeFloatBig(float val) { + val = utility::BigFloat(val); + writeUBytes((atUint8*)&val, 4); + } + void writeValBig(float val) { 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. + * + * @param val The value to write to the buffer + */ + void writeDouble(double val) { + if (m_endian == Big) + utility::BigDouble(val); + else + utility::LittleDouble(val); + writeUBytes((atUint8*)&val, 8); + } + void writeVal(double val) { writeDouble(val); } + + /** @brief Writes an double to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeDoubleLittle(double val) { + utility::LittleDouble(val); + writeUBytes((atUint8*)&val, 8); + } + void writeValLittle(double val) { writeDoubleLittle(val); } + + /** @brief Writes an double to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param val The value to write to the buffer + */ + void writeDoubleBig(double val) { + utility::BigDouble(val); + writeUBytes((atUint8*)&val, 8); + } + void writeValBig(double val) { 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. + * + * @param val The value to write to the buffer + */ + void writeBool(bool val) { writeUBytes((atUint8*)&val, 1); } + void writeVal(bool val) { writeBool(val); } + void writeValLittle(bool val) { writeBool(val); } + void writeValBig(bool val) { writeBool(val); } + + /** @brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + void writeVec2f(const atVec2f& vec) { + simd_floats tmp(vec.simd); + if (m_endian == Big) { + tmp[0] = utility::BigFloat(tmp[0]); + tmp[1] = utility::BigFloat(tmp[1]); + } else { + tmp[0] = utility::LittleFloat(tmp[0]); + tmp[1] = utility::LittleFloat(tmp[1]); + } + writeUBytes((atUint8*)tmp.data(), 8); + } + void writeVal(const atVec2f& val) { writeVec2f(val); } + + /** @brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec2fLittle(const atVec2f& vec) { + simd_floats tmp(vec.simd); + tmp[0] = utility::LittleFloat(tmp[0]); + tmp[1] = utility::LittleFloat(tmp[1]); + writeUBytes((atUint8*)tmp.data(), 8); + } + void writeValLittle(const atVec2f& val) { writeVec2fLittle(val); } + + /** @brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec2fBig(const atVec2f& vec) { + simd_floats tmp(vec.simd); + tmp[0] = utility::BigFloat(tmp[0]); + tmp[1] = utility::BigFloat(tmp[1]); + writeUBytes((atUint8*)tmp.data(), 8); + } + void writeValBig(const atVec2f& val) { 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. + * + * @param vec The value to write to the buffer + */ + void writeVec3f(const atVec3f& vec) { + simd_floats tmp(vec.simd); + if (m_endian == Big) { + tmp[0] = utility::BigFloat(tmp[0]); + tmp[1] = utility::BigFloat(tmp[1]); + tmp[2] = utility::BigFloat(tmp[2]); + } else { + tmp[0] = utility::LittleFloat(tmp[0]); + tmp[1] = utility::LittleFloat(tmp[1]); + tmp[2] = utility::LittleFloat(tmp[2]); + } + writeUBytes((atUint8*)tmp.data(), 12); + } + void writeVal(const atVec3f& val) { writeVec3f(val); } + + /** @brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec3fLittle(const atVec3f& vec) { + simd_floats tmp(vec.simd); + tmp[0] = utility::LittleFloat(tmp[0]); + tmp[1] = utility::LittleFloat(tmp[1]); + tmp[2] = utility::LittleFloat(tmp[2]); + writeUBytes((atUint8*)tmp.data(), 12); + } + void writeValLittle(const atVec3f& val) { writeVec3fLittle(val); } + + /** @brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec3fBig(const atVec3f& vec) { + simd_floats tmp(vec.simd); + tmp[0] = utility::BigFloat(tmp[0]); + tmp[1] = utility::BigFloat(tmp[1]); + tmp[2] = utility::BigFloat(tmp[2]); + writeUBytes((atUint8*)tmp.data(), 12); + } + void writeValBig(const atVec3f& val) { 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. + * + * @param vec The value to write to the buffer + */ + void writeVec4f(const atVec4f& vec) { + simd_floats tmp(vec.simd); + if (m_endian == Big) { + tmp[0] = utility::BigFloat(tmp[0]); + tmp[1] = utility::BigFloat(tmp[1]); + tmp[2] = utility::BigFloat(tmp[2]); + tmp[3] = utility::BigFloat(tmp[3]); + } else { + tmp[0] = utility::LittleFloat(tmp[0]); + tmp[1] = utility::LittleFloat(tmp[1]); + tmp[2] = utility::LittleFloat(tmp[2]); + tmp[3] = utility::LittleFloat(tmp[3]); + } + writeUBytes((atUint8*)tmp.data(), 16); + } + void writeVal(const atVec4f& val) { writeVec4f(val); } + + /** @brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec4fLittle(const atVec4f& vec) { + simd_floats tmp(vec.simd); + tmp[0] = utility::LittleFloat(tmp[0]); + tmp[1] = utility::LittleFloat(tmp[1]); + tmp[2] = utility::LittleFloat(tmp[2]); + tmp[3] = utility::LittleFloat(tmp[3]); + writeUBytes((atUint8*)tmp.data(), 16); + } + void writeValLittle(const atVec4f& val) { writeVec4fLittle(val); } + + /** @brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec4fBig(const atVec4f& vec) { + simd_floats tmp(vec.simd); + tmp[0] = utility::BigFloat(tmp[0]); + tmp[1] = utility::BigFloat(tmp[1]); + tmp[2] = utility::BigFloat(tmp[2]); + tmp[3] = utility::BigFloat(tmp[3]); + writeUBytes((atUint8*)tmp.data(), 16); + } + void writeValBig(const atVec4f& val) { writeVec4fBig(val); } + + /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + void writeVec2d(const atVec2d& vec) { + simd_doubles tmp(vec.simd); + if (m_endian == Big) { + tmp[0] = utility::BigDouble(tmp[0]); + tmp[1] = utility::BigDouble(tmp[1]); + } else { + tmp[0] = utility::LittleDouble(tmp[0]); + tmp[1] = utility::LittleDouble(tmp[1]); + } + writeUBytes((atUint8*)tmp.data(), 16); + } + void writeVal(const atVec2d& val) { writeVec2d(val); } + + /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec2dLittle(const atVec2d& vec) { + simd_doubles tmp(vec.simd); + tmp[0] = utility::LittleDouble(tmp[0]); + tmp[1] = utility::LittleDouble(tmp[1]); + writeUBytes((atUint8*)tmp.data(), 16); + } + void writeValLittle(const atVec2d& val) { writeVec2dLittle(val); } + + /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec2dBig(const atVec2d& vec) { + simd_doubles tmp(vec.simd); + tmp[0] = utility::BigDouble(tmp[0]); + tmp[1] = utility::BigDouble(tmp[1]); + writeUBytes((atUint8*)tmp.data(), 16); + } + void writeValBig(const atVec2d& val) { writeVec2dBig(val); } + + /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + void writeVec3d(const atVec3d& vec) { + simd_doubles tmp(vec.simd); + if (m_endian == Big) { + tmp[0] = utility::BigDouble(tmp[0]); + tmp[1] = utility::BigDouble(tmp[1]); + tmp[2] = utility::BigDouble(tmp[2]); + } else { + tmp[0] = utility::LittleDouble(tmp[0]); + tmp[1] = utility::LittleDouble(tmp[1]); + tmp[2] = utility::LittleDouble(tmp[2]); + } + writeUBytes((atUint8*)tmp.data(), 24); + } + void writeVal(const atVec3d& val) { writeVec3d(val); } + + /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec3dLittle(const atVec3d& vec) { + simd_doubles tmp(vec.simd); + tmp[0] = utility::LittleDouble(tmp[0]); + tmp[1] = utility::LittleDouble(tmp[1]); + tmp[2] = utility::LittleDouble(tmp[2]); + writeUBytes((atUint8*)tmp.data(), 24); + } + void writeValLittle(const atVec3d& val) { writeVec3dLittle(val); } + + /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec3dBig(const atVec3d& vec) { + simd_doubles tmp(vec.simd); + tmp[0] = utility::BigDouble(tmp[0]); + tmp[1] = utility::BigDouble(tmp[1]); + tmp[2] = utility::BigDouble(tmp[2]); + writeUBytes((atUint8*)tmp.data(), 24); + } + void writeValBig(const atVec3d& val) { writeVec3dBig(val); } + + /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + void writeVec4d(const atVec4d& vec) { + simd_doubles tmp(vec.simd); + if (m_endian == Big) { + tmp[0] = utility::BigDouble(tmp[0]); + tmp[1] = utility::BigDouble(tmp[1]); + tmp[2] = utility::BigDouble(tmp[2]); + tmp[3] = utility::BigDouble(tmp[3]); + } else { + tmp[0] = utility::LittleDouble(tmp[0]); + tmp[1] = utility::LittleDouble(tmp[1]); + tmp[2] = utility::LittleDouble(tmp[2]); + tmp[3] = utility::LittleDouble(tmp[3]); + } + writeUBytes((atUint8*)tmp.data(), 32); + } + void writeVal(const atVec4d& val) { writeVec4d(val); } + + /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec4dLittle(const atVec4d& vec) { + simd_doubles tmp(vec.simd); + tmp[0] = utility::LittleDouble(tmp[0]); + tmp[1] = utility::LittleDouble(tmp[1]); + tmp[2] = utility::LittleDouble(tmp[2]); + tmp[3] = utility::LittleDouble(tmp[3]); + writeUBytes((atUint8*)tmp.data(), 32); + } + void writeValLittle(const atVec4d& val) { writeVec4dLittle(val); } + + /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + void writeVec4dBig(const atVec4d& vec) { + simd_doubles tmp(vec.simd); + tmp[0] = utility::BigDouble(tmp[0]); + tmp[1] = utility::BigDouble(tmp[1]); + tmp[2] = utility::BigDouble(tmp[2]); + tmp[3] = utility::BigDouble(tmp[3]); + writeUBytes((atUint8*)tmp.data(), 32); + } + void writeValBig(const atVec4d& val) { writeVec4dBig(val); } + + /** @brief Converts a UTF8 string to a wide-char string in the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param str The string to write to the buffer + * @param fixedLen If not -1, the number of characters to zero-fill string to + * + * Endianness is set with setEndian + */ + void writeStringAsWString(std::string_view str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + std::string tmpStr = std::string("\xEF\xBB\xBF") + str.data(); + const utf8proc_uint8_t* buf = reinterpret_cast(tmpStr.c_str()); + if (fixedLen < 0) { + while (*buf) { + utf8proc_int32_t wc; + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); + return; + } + buf += len; + if (wc != 0xFEFF) + writeUint16(atUint16(wc)); + } + writeUint16(0); + } else { + for (atInt32 i = 0; i < fixedLen; ++i) { + utf8proc_int32_t wc = 0; + if (*buf) { + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); return; - for (atInt64 i=0 ; i= length();} - - /** @brief Returns the current position in the stream. - * - * @return The current position in the stream. - */ - virtual atUint64 position() const=0; - - /** @brief Returns whether or not the stream is at the end. - * - * @return True if at end; False otherwise. - */ - virtual atUint64 length() const=0; - - /** @brief Writes a byte at the current position and advances the position by one byte. - * @param val The value to write - */ - void writeUByte(atUint8 val) {writeUBytes(&val, 1);} - void writeVal(atUint8 val) {writeUByte(val);} - void writeValLittle(atUint8 val) {writeUByte(val);} - void writeValBig(atUint8 val) {writeUByte(val);} - - /** @brief Writes a byte at the current position and advances the position by one byte. - * @param val The value to write - */ - void writeByte(atInt8 val) {writeUByte(val);} - void writeVal(atInt8 val) {writeByte(val);} - void writeValLittle(atInt8 val) {writeByte(val);} - void writeValBig(atInt8 val) {writeByte(val);} - - /** @brief Writes the given buffer with the specified length, buffers can be bigger than the length - * however it's undefined behavior to try and write a buffer which is smaller than the given length. - * - * @param data The buffer to write - * @param length The amount to write - */ - virtual void writeUBytes(const atUint8* data, atUint64 len)=0; - - /** @brief Writes the given buffer with the specified length, buffers can be bigger than the length - * however it's undefined behavior to try and write a buffer which is smaller than the given length. - * - * @param data The buffer to write - * @param length The amount to write - */ - void writeBytes(const void* data, atUint64 len) {writeUBytes((atUint8*)data, len);} - - /** @brief Writes an Int16 to the buffer and advances the buffer. - * It also swaps the bytes depending on the platform and Stream settings. - * - * @param val The value to write to the buffer - */ - void writeInt16(atInt16 val) - { - if (m_endian == Big) - utility::BigInt16(val); - else - utility::LittleInt16(val); - writeUBytes((atUint8*)&val, 2); - } - void writeVal(atInt16 val) {writeInt16(val);} - - /** @brief Writes an Int16 to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeInt16Little(atInt16 val) - { - utility::LittleInt16(val); - writeUBytes((atUint8*)&val, 2); - } - void writeValLittle(atInt16 val) {writeInt16Little(val);} - - /** @brief Writes an Int16 to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeInt16Big(atInt16 val) - { - utility::BigInt16(val); - writeUBytes((atUint8*)&val, 2); - } - void writeValBig(atInt16 val) {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 - * - * @param val The value to write to the buffer - */ - void writeUint16(atUint16 val) {writeInt16(val);} - void writeVal(atUint16 val) {writeUint16(val);} - - /** @brief Writes an Uint16 to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform - * - * @param val The value to write to the buffer - */ - void writeUint16Little(atUint16 val) {writeInt16Little(val);} - void writeValLittle(atUint16 val) {writeUint16Little(val);} - - /** @brief Writes an Uint16 to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform - * - * @param val The value to write to the buffer - */ - void writeUint16Big(atUint16 val) {writeInt16Big(val);} - void writeValBig(atUint16 val) {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. - * - * @param val The value to write to the buffer - */ - void writeInt32(atInt32 val) - { - if (m_endian == Big) - utility::BigInt32(val); - else - utility::LittleInt32(val); - writeUBytes((atUint8*)&val, 4); - } - void writeVal(atInt32 val) {writeInt32(val);} - - /** @brief Writes an Int32 to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeInt32Little(atInt32 val) - { - utility::LittleInt32(val); - writeUBytes((atUint8*)&val, 4); - } - void writeValLittle(atInt32 val) {writeInt32Little(val);} - - /** @brief Writes an Int32 to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeInt32Big(atInt32 val) - { - utility::BigInt32(val); - writeUBytes((atUint8*)&val, 4); - } - void writeValBig(atInt32 val) {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. - * - * @param val The value to write to the buffer - */ - void writeUint32(atUint32 val) {writeInt32(val);} - void writeVal(atUint32 val) {writeUint32(val);} - - /** @brief Writes an Uint32 to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeUint32Little(atUint32 val) {writeInt32Little(val);} - void writeValLittle(atUint32 val) {writeUint32Little(val);} - - /** @brief Writes an Uint32 to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeUint32Big(atUint32 val) {writeInt32Big(val);} - void writeValBig(atUint32 val) {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. - * - * @param val The value to write to the buffer - */ - void writeInt64(atInt64 val) - { - if (m_endian == Big) - utility::BigInt64(val); - else - utility::LittleInt64(val); - writeUBytes((atUint8*)&val, 8); - } - void writeVal(atInt64 val) {writeInt64(val);} - - /** @brief Writes an Int64 to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeInt64Little(atInt64 val) - { - utility::LittleInt64(val); - writeUBytes((atUint8*)&val, 8); - } - void writeValLittle(atInt64 val) {writeInt64Little(val);} - - /** @brief Writes an Int64 to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeInt64Big(atInt64 val) - { - utility::BigInt64(val); - writeUBytes((atUint8*)&val, 8); - } - void writeValBig(atInt64 val) {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. - * - * @param val The value to write to the buffer - */ - void writeUint64(atUint64 val) {writeInt64(val);} - void writeVal(atUint64 val) {writeUint64(val);} - - /** @brief Writes an Uint64 to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeUint64Little(atUint64 val) {writeInt64Little(val);} - void writeValLittle(atUint64 val) {writeUint64Little(val);} - - /** @brief Writes an Uint64 to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeUint64Big(atUint64 val) {writeInt64Big(val);} - void writeValBig(atUint64 val) {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. - * - * @param val The value to write to the buffer - */ - void writeFloat(float val) - { - if (m_endian == Big) - val = utility::BigFloat(val); - else - val = utility::LittleFloat(val); - writeUBytes((atUint8*)&val, 4); - } - void writeVal(float val) {writeFloat(val);} - - /** @brief Writes an float to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeFloatLittle(float val) - { - utility::LittleFloat(val); - writeUBytes((atUint8*)&val, 4); - } - void writeValLittle(float val) {writeFloatLittle(val);} - - /** @brief Writes an float to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeFloatBig(float val) - { - val = utility::BigFloat(val); - writeUBytes((atUint8*)&val, 4); - } - void writeValBig(float val) {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. - * - * @param val The value to write to the buffer - */ - void writeDouble(double val) - { - if (m_endian == Big) - utility::BigDouble(val); - else - utility::LittleDouble(val); - writeUBytes((atUint8*)&val, 8); - } - void writeVal(double val) {writeDouble(val);} - - /** @brief Writes an double to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeDoubleLittle(double val) - { - utility::LittleDouble(val); - writeUBytes((atUint8*)&val, 8); - } - void writeValLittle(double val) {writeDoubleLittle(val);} - - /** @brief Writes an double to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param val The value to write to the buffer - */ - void writeDoubleBig(double val) - { - utility::BigDouble(val); - writeUBytes((atUint8*)&val, 8); - } - void writeValBig(double val) {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. - * - * @param val The value to write to the buffer - */ - void writeBool(bool val) {writeUBytes((atUint8*)&val, 1);} - void writeVal(bool val) {writeBool(val);} - void writeValLittle(bool val) {writeBool(val);} - void writeValBig(bool val) {writeBool(val);} - - /** @brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer. - * It also swaps the bytes depending on the platform and Stream settings. - * - * @param vec The value to write to the buffer - */ - void writeVec2f(const atVec2f& vec) - { - simd_floats tmp(vec.simd); - if (m_endian == Big) - { - tmp[0] = utility::BigFloat(tmp[0]); - tmp[1] = utility::BigFloat(tmp[1]); + } + buf += len; } - else - { - tmp[0] = utility::LittleFloat(tmp[0]); - tmp[1] = utility::LittleFloat(tmp[1]); + + if (wc == 0xFEFF) { + --i; + continue; } - writeUBytes((atUint8*)tmp.data(), 8); - } - void writeVal(const atVec2f& val) {writeVec2f(val);} - /** @brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec2fLittle(const atVec2f& vec) - { - simd_floats tmp(vec.simd); - tmp[0] = utility::LittleFloat(tmp[0]); - tmp[1] = utility::LittleFloat(tmp[1]); - writeUBytes((atUint8*)tmp.data(), 8); + writeUint16(atUint16(wc)); + } } - void writeValLittle(const atVec2f& val) {writeVec2fLittle(val);} + } - /** @brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec2fBig(const atVec2f& vec) - { - simd_floats tmp(vec.simd); - tmp[0] = utility::BigFloat(tmp[0]); - tmp[1] = utility::BigFloat(tmp[1]); - writeUBytes((atUint8*)tmp.data(), 8); - } - void writeValBig(const atVec2f& val) {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. - * - * @param vec The value to write to the buffer - */ - void writeVec3f(const atVec3f& vec) - { - simd_floats tmp(vec.simd); - if (m_endian == Big) - { - tmp[0] = utility::BigFloat(tmp[0]); - tmp[1] = utility::BigFloat(tmp[1]); - tmp[2] = utility::BigFloat(tmp[2]); + /** @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. + * + * @param str The string to write to the buffer + * @param fixedLen If not -1, the number of characters to zero-fill string to + * + * Endianness is little + */ + void writeStringAsWStringLittle(std::string_view str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + std::string tmpStr = std::string("\xEF\xBB\xBF") + str.data(); + const utf8proc_uint8_t* buf = reinterpret_cast(tmpStr.c_str()); + if (fixedLen < 0) { + while (*buf) { + utf8proc_int32_t wc; + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); + return; } - else - { - tmp[0] = utility::LittleFloat(tmp[0]); - tmp[1] = utility::LittleFloat(tmp[1]); - tmp[2] = utility::LittleFloat(tmp[2]); - } - writeUBytes((atUint8*)tmp.data(), 12); - } - void writeVal(const atVec3f& val) {writeVec3f(val);} - - /** @brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec3fLittle(const atVec3f& vec) - { - simd_floats tmp(vec.simd); - tmp[0] = utility::LittleFloat(tmp[0]); - tmp[1] = utility::LittleFloat(tmp[1]); - tmp[2] = utility::LittleFloat(tmp[2]); - writeUBytes((atUint8*)tmp.data(), 12); - } - void writeValLittle(const atVec3f& val) {writeVec3fLittle(val);} - - /** @brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec3fBig(const atVec3f& vec) - { - simd_floats tmp(vec.simd); - tmp[0] = utility::BigFloat(tmp[0]); - tmp[1] = utility::BigFloat(tmp[1]); - tmp[2] = utility::BigFloat(tmp[2]); - writeUBytes((atUint8*)tmp.data(), 12); - } - void writeValBig(const atVec3f& val) {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. - * - * @param vec The value to write to the buffer - */ - void writeVec4f(const atVec4f& vec) - { - simd_floats tmp(vec.simd); - if (m_endian == Big) - { - tmp[0] = utility::BigFloat(tmp[0]); - tmp[1] = utility::BigFloat(tmp[1]); - tmp[2] = utility::BigFloat(tmp[2]); - tmp[3] = utility::BigFloat(tmp[3]); - } - else - { - tmp[0] = utility::LittleFloat(tmp[0]); - tmp[1] = utility::LittleFloat(tmp[1]); - tmp[2] = utility::LittleFloat(tmp[2]); - tmp[3] = utility::LittleFloat(tmp[3]); - } - writeUBytes((atUint8*)tmp.data(), 16); - } - void writeVal(const atVec4f& val) {writeVec4f(val);} - - /** @brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec4fLittle(const atVec4f& vec) - { - simd_floats tmp(vec.simd); - tmp[0] = utility::LittleFloat(tmp[0]); - tmp[1] = utility::LittleFloat(tmp[1]); - tmp[2] = utility::LittleFloat(tmp[2]); - tmp[3] = utility::LittleFloat(tmp[3]); - writeUBytes((atUint8*)tmp.data(), 16); - } - void writeValLittle(const atVec4f& val) {writeVec4fLittle(val);} - - /** @brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec4fBig(const atVec4f& vec) - { - simd_floats tmp(vec.simd); - tmp[0] = utility::BigFloat(tmp[0]); - tmp[1] = utility::BigFloat(tmp[1]); - tmp[2] = utility::BigFloat(tmp[2]); - tmp[3] = utility::BigFloat(tmp[3]); - writeUBytes((atUint8*)tmp.data(), 16); - } - void writeValBig(const atVec4f& val) {writeVec4fBig(val);} - - /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. - * It also swaps the bytes depending on the platform and Stream settings. - * - * @param vec The value to write to the buffer - */ - void writeVec2d(const atVec2d& vec) - { - simd_doubles tmp(vec.simd); - if (m_endian == Big) - { - tmp[0] = utility::BigDouble(tmp[0]); - tmp[1] = utility::BigDouble(tmp[1]); - } - else - { - tmp[0] = utility::LittleDouble(tmp[0]); - tmp[1] = utility::LittleDouble(tmp[1]); - } - writeUBytes((atUint8*)tmp.data(), 16); - } - void writeVal(const atVec2d& val) {writeVec2d(val);} - - /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec2dLittle(const atVec2d& vec) - { - simd_doubles tmp(vec.simd); - tmp[0] = utility::LittleDouble(tmp[0]); - tmp[1] = utility::LittleDouble(tmp[1]); - writeUBytes((atUint8*)tmp.data(), 16); - } - void writeValLittle(const atVec2d& val) {writeVec2dLittle(val);} - - /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec2dBig(const atVec2d& vec) - { - simd_doubles tmp(vec.simd); - tmp[0] = utility::BigDouble(tmp[0]); - tmp[1] = utility::BigDouble(tmp[1]); - writeUBytes((atUint8*)tmp.data(), 16); - } - void writeValBig(const atVec2d& val) {writeVec2dBig(val);} - - /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. - * It also swaps the bytes depending on the platform and Stream settings. - * - * @param vec The value to write to the buffer - */ - void writeVec3d(const atVec3d& vec) - { - simd_doubles tmp(vec.simd); - if (m_endian == Big) - { - tmp[0] = utility::BigDouble(tmp[0]); - tmp[1] = utility::BigDouble(tmp[1]); - tmp[2] = utility::BigDouble(tmp[2]); - } - else - { - tmp[0] = utility::LittleDouble(tmp[0]); - tmp[1] = utility::LittleDouble(tmp[1]); - tmp[2] = utility::LittleDouble(tmp[2]); - } - writeUBytes((atUint8*)tmp.data(), 24); - } - void writeVal(const atVec3d& val) {writeVec3d(val);} - - /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec3dLittle(const atVec3d& vec) - { - simd_doubles tmp(vec.simd); - tmp[0] = utility::LittleDouble(tmp[0]); - tmp[1] = utility::LittleDouble(tmp[1]); - tmp[2] = utility::LittleDouble(tmp[2]); - writeUBytes((atUint8*)tmp.data(), 24); - } - void writeValLittle(const atVec3d& val) {writeVec3dLittle(val);} - - /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec3dBig(const atVec3d& vec) - { - simd_doubles tmp(vec.simd); - tmp[0] = utility::BigDouble(tmp[0]); - tmp[1] = utility::BigDouble(tmp[1]); - tmp[2] = utility::BigDouble(tmp[2]); - writeUBytes((atUint8*)tmp.data(), 24); - } - void writeValBig(const atVec3d& val) {writeVec3dBig(val);} - - /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. - * It also swaps the bytes depending on the platform and Stream settings. - * - * @param vec The value to write to the buffer - */ - void writeVec4d(const atVec4d& vec) - { - simd_doubles tmp(vec.simd); - if (m_endian == Big) - { - tmp[0] = utility::BigDouble(tmp[0]); - tmp[1] = utility::BigDouble(tmp[1]); - tmp[2] = utility::BigDouble(tmp[2]); - tmp[3] = utility::BigDouble(tmp[3]); - } - else - { - tmp[0] = utility::LittleDouble(tmp[0]); - tmp[1] = utility::LittleDouble(tmp[1]); - tmp[2] = utility::LittleDouble(tmp[2]); - tmp[3] = utility::LittleDouble(tmp[3]); - } - writeUBytes((atUint8*)tmp.data(), 32); - } - void writeVal(const atVec4d& val) {writeVec4d(val);} - - /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against little depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec4dLittle(const atVec4d& vec) - { - simd_doubles tmp(vec.simd); - tmp[0] = utility::LittleDouble(tmp[0]); - tmp[1] = utility::LittleDouble(tmp[1]); - tmp[2] = utility::LittleDouble(tmp[2]); - tmp[3] = utility::LittleDouble(tmp[3]); - writeUBytes((atUint8*)tmp.data(), 32); - } - void writeValLittle(const atVec4d& val) {writeVec4dLittle(val);} - - /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. - * It also swaps the bytes against big depending on the platform. - * - * @param vec The value to write to the buffer - */ - void writeVec4dBig(const atVec4d& vec) - { - simd_doubles tmp(vec.simd); - tmp[0] = utility::BigDouble(tmp[0]); - tmp[1] = utility::BigDouble(tmp[1]); - tmp[2] = utility::BigDouble(tmp[2]); - tmp[3] = utility::BigDouble(tmp[3]); - writeUBytes((atUint8*)tmp.data(), 32); - } - void writeValBig(const atVec4d& val) {writeVec4dBig(val);} - - /** @brief Converts a UTF8 string to a wide-char string in the buffer and advances the buffer. - * It also swaps the bytes depending on the platform and Stream settings. - * - * @param str The string to write to the buffer - * @param fixedLen If not -1, the number of characters to zero-fill string to - * - * Endianness is set with setEndian - */ - void writeStringAsWString(std::string_view str, atInt32 fixedLen = -1) - { - if (fixedLen == 0) + buf += len; + if (wc != 0xFEFF) + writeUint16Little(atUint16(wc)); + } + writeUint16Little(0); + } else { + for (atInt32 i = 0; i < fixedLen; ++i) { + utf8proc_int32_t wc = 0; + if (*buf) { + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); return; - std::string tmpStr = std::string("\xEF\xBB\xBF") + str.data(); - const utf8proc_uint8_t* buf = reinterpret_cast(tmpStr.c_str()); - if (fixedLen < 0) - { - while (*buf) - { - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) - { - atWarning("invalid UTF-8 character while decoding"); - return; - } - buf += len; - if (wc != 0xFEFF) - writeUint16(atUint16(wc)); - } - writeUint16(0); + } + buf += len; } - else - { - for (atInt32 i=0 ; i(tmpStr.c_str()); + if (fixedLen < 0) { + while (*buf) { + utf8proc_int32_t wc; + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); + return; + } + buf += len; + if (wc != 0xFEFF) + writeUint16Big(atUint16(wc)); + } + writeUint16Big(0); + } else { + for (atInt32 i = 0; i < fixedLen; ++i) { + utf8proc_int32_t wc = 0; + if (*buf) { + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); return; - std::string tmpStr = std::string("\xEF\xBB\xBF") + str.data(); - const utf8proc_uint8_t* buf = reinterpret_cast(tmpStr.c_str()); - if (fixedLen < 0) - { - while (*buf) - { - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) - { - atWarning("invalid UTF-8 character while decoding"); - return; - } - buf += len; - if (wc != 0xFEFF) - writeUint16Little(atUint16(wc)); - } - writeUint16Little(0); + } + buf += len; } + + if (wc == 0xFEFF) { + --i; + continue; + } + + writeUint16Big(atUint16(wc)); + } + } + } + + /** @brief Writes an string to the buffer and advances the buffer. + * + * @param str The string to write to the buffer + * @param fixedLen If not -1, the number of characters to zero-fill string to + */ + void writeString(std::string_view str, atInt32 fixedLen = -1) { + if (fixedLen == 0) + return; + + if (fixedLen < 0) { + for (atUint8 c : str) { + writeUByte(c); + + if (c == '\0') + break; + } + writeUByte(0); + } else { + auto it = str.begin(); + for (atInt32 i = 0; i < fixedLen; ++i) { + atUint8 chr; + if (it == str.end()) + chr = 0; else - { - for (atInt32 i=0 ; i(tmpStr.c_str()); - if (fixedLen < 0) - { - while (*buf) - { - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) - { - atWarning("invalid UTF-8 character while decoding"); - return; - } - buf += len; - if (wc != 0xFEFF) - writeUint16Big(atUint16(wc)); - } - writeUint16Big(0); - } + if (fixedLen < 0) { + for (atUint16 c : str) { + writeUint16(c); + + if (c == L'\0') + break; + } + writeUint16(0); + } else { + auto it = str.begin(); + for (atInt32 i = 0; i < fixedLen; ++i) { + atUint16 chr; + if (it == str.end()) + chr = 0; else - { - for (atInt32 i=0 ; i tmp(new atUint8[length]); + memset(tmp.get(), val, length); + writeUBytes(tmp.get(), length); + } - if (c == u'\0') - break; - } - writeUint16Big(0); - } - else - { - auto it = str.begin(); - for (atInt32 i=0 ; i + void + enumerate(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) + writeVal(item); + } - if (fixedLen < 0) - { - for (char32_t c : str) - { - writeUint32Big(c); + /** @brief Performs automatic std::vector enumeration writes using numeric type T + * @param vector The std::vector read from when writing data + * + * Endianness is little + */ + template + 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); + } - if (c == U'\0') - break; - } - writeUint32Big(0); - } - else - { - auto it = str.begin(); - for (atInt32 i=0 ; i + 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); + } - void fill(atUint8 val, atUint64 length) - { - if (length == 0) - return; - - std::unique_ptr tmp(new atUint8[length]); - memset(tmp.get(), val, length); - writeUBytes(tmp.get(), length); - } - - void fill(atInt8 val, atUint64 length) - {fill((atUint8)val, length);} - - /** @brief Performs automatic std::vector enumeration writes using numeric type T - * @param vector The std::vector read from when writing data - * - * Endianness is set with setEndian - */ - template - void enumerate(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) - writeVal(item); - } - - /** @brief Performs automatic std::vector enumeration writes using numeric type T - * @param vector The std::vector read from when writing data - * - * Endianness is little - */ - template - 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); - } - - /** @brief Performs automatic std::vector enumeration writes using numeric type T - * @param vector The std::vector read from when writing data - * - * Endianness is big - */ - 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); - } - - /** @brief Performs automatic std::vector enumeration writes using non-numeric type T - * @param vector The std::vector read from when writing data - */ - template - void enumerate(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) - item.write(*this); - } + /** @brief Performs automatic std::vector enumeration writes using non-numeric type T + * @param vector The std::vector read from when writing data + */ + template + void + enumerate(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) + item.write(*this); + } }; template -IStreamWriter& operator<<(IStreamWriter& lhs, const T& rhs) -{ - lhs.writeVal(rhs); - return lhs; +IStreamWriter& operator<<(IStreamWriter& lhs, const T& rhs) { + lhs.writeVal(rhs); + return lhs; } -} - +} // namespace athena::io diff --git a/include/athena/MCFile.hpp b/include/athena/MCFile.hpp index 9e0db23..c9c8206 100644 --- a/include/athena/MCFile.hpp +++ b/include/athena/MCFile.hpp @@ -2,8 +2,7 @@ #include "athena/Global.hpp" -namespace athena -{ +namespace athena { class MCSlot; /*! \class MCFile @@ -12,23 +11,18 @@ class MCSlot; * Contains all relevant data for a The Minish Cap save, * file. */ -class MCFile -{ +class MCFile { public: - static const char VERSION_EU_JP[33]; - static const char VERSION_US[33]; - enum SlotType - { - New = 0x54494E49, - Valid = 0x4D435A33, - Deleted = 0x466C6544 - }; + static const char VERSION_EU_JP[33]; + static const char VERSION_US[33]; + enum SlotType { New = 0x54494E49, Valid = 0x4D435A33, Deleted = 0x466C6544 }; - MCFile(); + MCFile(); + + static atUint8* unscramble(atUint8* data, atUint64 length); - static atUint8* unscramble(atUint8* data, atUint64 length); private: - MCSlot* m_slots[3]; + MCSlot* m_slots[3]; }; -} // zelda +} // namespace athena diff --git a/include/athena/MCFileReader.hpp b/include/athena/MCFileReader.hpp index 4b90bde..6900a6e 100644 --- a/include/athena/MCFileReader.hpp +++ b/include/athena/MCFileReader.hpp @@ -2,13 +2,11 @@ #include "athena/MemoryReader.hpp" -namespace athena -{ +namespace athena { class MCFile; -namespace io -{ +namespace io { /*! \class MCFileReader * \brief The Minish Cap Save save data reader class @@ -17,32 +15,30 @@ namespace io * all work is done using a memory buffer, and not read directly from the disk. * \sa BinaryReader */ -class MCFileReader : public MemoryCopyReader -{ +class MCFileReader : public MemoryCopyReader { public: - /*! - * \brief This constructor takes an existing buffer to read from. - * - * \param data The existing buffer - * \param length The length of the existing buffer - */ - MCFileReader(atUint8*, atUint64); + /*! + * \brief This constructor takes an existing buffer to read from. + * + * \param data The existing buffer + * \param length The length of the existing buffer + */ + MCFileReader(atUint8*, atUint64); - /*! - * \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - MCFileReader(const std::string&); + /*! + * \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + MCFileReader(const std::string&); - /*! - * \brief Reads the save data from the buffer - * - * \return MCFile* SRAM data - */ - MCFile* readFile(); + /*! + * \brief Reads the save data from the buffer + * + * \return MCFile* SRAM data + */ + MCFile* readFile(); }; -} // io -} // zelda - +} // namespace io +} // namespace athena diff --git a/include/athena/MCFileWriter.hpp b/include/athena/MCFileWriter.hpp index a71ceec..29b1991 100644 --- a/include/athena/MCFileWriter.hpp +++ b/include/athena/MCFileWriter.hpp @@ -3,13 +3,11 @@ #include "athena/Types.hpp" #include "athena/MemoryWriter.hpp" -namespace athena -{ +namespace athena { class MCFile; -namespace io -{ +namespace io { /*! \class MCFileWriter * \brief The Minish Cap Save save data writer class @@ -18,36 +16,35 @@ namespace io * all work is done using a memory buffer, and not written directly from the disk. * \sa BinaryWriter */ -class MCFileWriter : protected MemoryCopyWriter -{ +class MCFileWriter : protected MemoryCopyWriter { public: - /*! - * \brief This constructor takes an existing buffer to write to. - * - * \param data The existing buffer - * \param length The length of the existing buffer - */ - MCFileWriter(atUint8*, atUint64); + /*! + * \brief This constructor takes an existing buffer to write to. + * + * \param data The existing buffer + * \param length The length of the existing buffer + */ + MCFileWriter(atUint8*, atUint64); - /*! - * \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - MCFileWriter(const std::string&); + /*! + * \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + MCFileWriter(const std::string&); - /*! - * \brief Writes the given save data to a file on disk - * - * \param file Save data to write - */ - void writeFile(MCFile* file); + /*! + * \brief Writes the given save data to a file on disk + * + * \param file Save data to write + */ + void writeFile(MCFile* file); + + static atUint16 calculateChecksum(atUint8* data, atUint32 length); - static atUint16 calculateChecksum(atUint8* data, atUint32 length); private: - atUint16 calculateSlotChecksum(atUint32 game); + atUint16 calculateSlotChecksum(atUint32 game); }; -} // io -} // zelda - +} // namespace io +} // namespace athena diff --git a/include/athena/MCSlot.hpp b/include/athena/MCSlot.hpp index c5dceb9..98fbff1 100644 --- a/include/athena/MCSlot.hpp +++ b/include/athena/MCSlot.hpp @@ -3,13 +3,10 @@ #include "athena/Global.hpp" #include "athena/ZQuestFile.hpp" -namespace athena -{ -class MCSlot : public ZQuestFile -{ +namespace athena { +class MCSlot : public ZQuestFile { public: - MCSlot(std::unique_ptr&& data, atUint32 length); + MCSlot(std::unique_ptr&& data, atUint32 length); }; -} // Athena - +} // namespace athena diff --git a/include/athena/MemoryReader.hpp b/include/athena/MemoryReader.hpp index b1bea27..1a82c27 100644 --- a/include/athena/MemoryReader.hpp +++ b/include/athena/MemoryReader.hpp @@ -5,8 +5,7 @@ #include #include "athena/IStreamReader.hpp" -namespace athena::io -{ +namespace athena::io { /*! \class MemoryReader * \brief A Stream class for reading data from a memory position * @@ -15,106 +14,97 @@ namespace athena::io * this allows for fast, flexible code as well as the ability to quickly modify data * \sa Stream */ -class MemoryReader : public IStreamReader -{ +class MemoryReader : public IStreamReader { protected: - MemoryReader() = default; + MemoryReader() = default; + public: - virtual ~MemoryReader(); + virtual ~MemoryReader(); - /*! \brief This constructor references an existing buffer to read from. - * - * \param data The existing buffer - * \param length The length of the existing buffer - * \param takeOwnership Memory will be freed with the reader if set - */ - MemoryReader(const void* data, atUint64 length, bool takeOwnership=false, bool globalErr=true); + /*! \brief This constructor references an existing buffer to read from. + * + * \param data The existing buffer + * \param length The length of the existing buffer + * \param takeOwnership Memory will be freed with the reader if set + */ + MemoryReader(const void* data, atUint64 length, bool takeOwnership = false, bool globalErr = true); - /*! \brief Sets the buffers position relative to the specified position.
- * It seeks relative to the current position by default. - * \param position where in the buffer to seek - * \param origin The Origin to seek \sa SeekOrigin - */ - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + /*! \brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * \param position where in the buffer to seek + * \param origin The Origin to seek \sa SeekOrigin + */ + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - /*! \brief Returns the current position in the stream. - * - * \return Int64 The current position in the stream. - */ - inline atUint64 position() const - {return m_position;} + /*! \brief Returns the current position in the stream. + * + * \return Int64 The current position in the stream. + */ + inline atUint64 position() const { return m_position; } - /*! \brief Returns whether or not the stream is at the end. - * - * \return bool True if at end; False otherwise. - */ - inline atUint64 length() const - {return m_length;} + /*! \brief Returns whether or not the stream is at the end. + * + * \return bool True if at end; False otherwise. + */ + inline atUint64 length() const { return m_length; } + /*! \brief Sets the buffer to the given one, deleting the current one.
+ * BEWARE: As this deletes the current buffer it WILL cause a loss of data + * if that was not the intent.
+ * Once you pass the data to setData DO NOT delete the buffer + * as Stream now owns the address, this is done to keep memory usage down. + * \param data The new buffer. + * \param length The length of the new buffer. + * \param takeOwnership Memory will be freed with the reader if set + * \throw IOException + */ + void setData(const atUint8* data, atUint64 length, bool takeOwnership = false); - /*! \brief Sets the buffer to the given one, deleting the current one.
- * BEWARE: As this deletes the current buffer it WILL cause a loss of data - * if that was not the intent.
- * Once you pass the data to setData DO NOT delete the buffer - * as Stream now owns the address, this is done to keep memory usage down. - * \param data The new buffer. - * \param length The length of the new buffer. - * \param takeOwnership Memory will be freed with the reader if set - * \throw IOException - */ - void setData(const atUint8* data, atUint64 length, bool takeOwnership=false); + /*! \brief Returns a copy of the current buffer.
+ * Changes to the copy do not affect the buffer so it's perfectly safe to + * directly edit the buffer and use setData to set the new information.
+ * However once you pass the data to setData DO NOT delete the buffer + * as Stream now owns the address, this is done to keep memory usage down. + * \return Uint8* The copy of the buffer. + */ + atUint8* data() const; - - /*! \brief Returns a copy of the current buffer.
- * Changes to the copy do not affect the buffer so it's perfectly safe to - * directly edit the buffer and use setData to set the new information.
- * However once you pass the data to setData DO NOT delete the buffer - * as Stream now owns the address, this is done to keep memory usage down. - * \return Uint8* The copy of the buffer. - */ - atUint8* data() const; - - /*! \brief Reads a specified number of bytes to user-allocated buffer - * \param buf User-allocated buffer pointer - * \param len Length to read - * \return Number of bytes read - */ - atUint64 readUBytesToBuf(void* buf, atUint64 len); + /*! \brief Reads a specified number of bytes to user-allocated buffer + * \param buf User-allocated buffer pointer + * \param len Length to read + * \return Number of bytes read + */ + atUint64 readUBytesToBuf(void* buf, atUint64 len); protected: - const void* m_data = nullptr; - atUint64 m_length = 0; - atUint64 m_position = 0; - bool m_owns = false; - bool m_globalErr = true; + const void* m_data = nullptr; + atUint64 m_length = 0; + atUint64 m_position = 0; + bool m_owns = false; + bool m_globalErr = true; }; -class MemoryCopyReader : public MemoryReader -{ +class MemoryCopyReader : public MemoryReader { public: - /*! \brief This constructor copies an existing buffer to read from. - * - * \param data The existing buffer - * \param length The length of the existing buffer - */ - MemoryCopyReader(const void* data, atUint64 length); + /*! \brief This constructor copies an existing buffer to read from. + * + * \param data The existing buffer + * \param length The length of the existing buffer + */ + MemoryCopyReader(const void* data, atUint64 length); - /*! \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - MemoryCopyReader(const std::string& filename) - : m_filepath(filename) - {loadData();} + /*! \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + MemoryCopyReader(const std::string& filename) : m_filepath(filename) { loadData(); } - void setData(const atUint8* data, atUint64 length); + void setData(const atUint8* data, atUint64 length); protected: - void loadData(); - std::unique_ptr m_dataCopy; - std::string m_filepath; //!< Path to the target file + void loadData(); + std::unique_ptr m_dataCopy; + std::string m_filepath; //!< Path to the target file }; -} // Athena - - +} // namespace athena::io diff --git a/include/athena/MemoryWriter.hpp b/include/athena/MemoryWriter.hpp index c5b064a..28c4d23 100644 --- a/include/athena/MemoryWriter.hpp +++ b/include/athena/MemoryWriter.hpp @@ -5,8 +5,7 @@ #include #include "athena/IStreamWriter.hpp" -namespace athena::io -{ +namespace athena::io { /*! @class MemoryWriter * @brief A Stream class for writing data to a memory position @@ -16,144 +15,133 @@ namespace athena::io * this allows for fast, flexible code as well as the ability to quickly modify data * @sa Stream */ -class MemoryWriter : public IStreamWriter -{ +class MemoryWriter : public IStreamWriter { public: + virtual ~MemoryWriter(); - virtual ~MemoryWriter(); + /*! @brief This constructor references an existing buffer to write to in-place. + * + * @param data The existing buffer + * @param length The length of the existing buffer + */ + explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false); - /*! @brief This constructor references an existing buffer to write to in-place. - * - * @param data The existing buffer - * @param length The length of the existing buffer - */ - explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false); + /*! @brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * @param position where in the buffer to seek + * @param origin The Origin to seek @sa SeekOrigin + */ + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - /*! @brief Sets the buffers position relative to the specified position.
- * It seeks relative to the current position by default. - * @param position where in the buffer to seek - * @param origin The Origin to seek @sa SeekOrigin - */ - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + /*! @brief Returns the current position in the stream. + * + * @return Int64 The current position in the stream. + */ + inline atUint64 position() const { return m_position; } + /*! @brief Returns the length of the stream. + * + * @return Int64 The length of the stream. + */ + inline atUint64 length() const { return m_length; } - /*! @brief Returns the current position in the stream. - * - * @return Int64 The current position in the stream. - */ - inline atUint64 position() const - {return m_position;} + inline bool isOpen() const { return true; } - /*! @brief Returns the length of the stream. - * - * @return Int64 The length of the stream. - */ - inline atUint64 length() const - {return m_length;} + /** @brief Sets the buffer to the given one, deleting the current one if it owns it.
+ * @param data The new buffer. + * @param length The length of the new buffer. + * @param takeOwnership Whether the Stream now owns the buffer. + */ + void setData(atUint8* data, atUint64 length, bool takeOwnership = false); - inline bool isOpen() const {return true;} + /*! @brief Returns a copy of the current buffer.
+ * Changes to the copy do not affect the buffer so it's perfectly safe to + * directly edit the buffer and use setData to set the new information.
+ * @return Uint8* The copy of the buffer. + */ + atUint8* data() const; - /** @brief Sets the buffer to the given one, deleting the current one if it owns it.
- * @param data The new buffer. - * @param length The length of the new buffer. - * @param takeOwnership Whether the Stream now owns the buffer. - */ - void setData(atUint8* data, atUint64 length, bool takeOwnership = false); + /*! @brief Sets the target file + * + * @param filepath The path to write to. + */ + inline void setFilepath(const std::string& filepath) { m_filepath = filepath; } + /*! @brief + * Returns the target file + */ + inline std::string filepath() const { return m_filepath; } - /*! @brief Returns a copy of the current buffer.
- * Changes to the copy do not affect the buffer so it's perfectly safe to - * directly edit the buffer and use setData to set the new information.
- * @return Uint8* The copy of the buffer. - */ - atUint8* data() const; + /*! @brief Saves the file to the specified file. + * + * @param filename If not empty, the filename to save to + */ + void save(std::string_view filename = {}); - /*! @brief Sets the target file - * - * @param filepath The path to write to. - */ - inline void setFilepath(const std::string& filepath) - {m_filepath = filepath;} - - /*! @brief - * Returns the target file - */ - inline std::string filepath() const - {return m_filepath;} - - - /*! @brief Saves the file to the specified file. - * - * @param filename If not empty, the filename to save to - */ - void save(std::string_view filename = {}); - - /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length - * however it's undefined behavior to try and write a buffer which is smaller than the given length. - * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. - * - * @param data The buffer to write - * @param length The amount to write - */ - void writeUBytes(const atUint8* data, atUint64 len); + /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length + * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. + * + * @param data The buffer to write + * @param length The amount to write + */ + void writeUBytes(const atUint8* data, atUint64 len); protected: - MemoryWriter() {} - atUint8* m_data; - atUint64 m_length; - atUint64 m_position; - bool m_bufferOwned; - std::string m_filepath; //!< Path to the target file + MemoryWriter() {} + atUint8* m_data; + atUint64 m_length; + atUint64 m_position; + bool m_bufferOwned; + std::string m_filepath; //!< Path to the target file }; -class MemoryCopyWriter : public MemoryWriter -{ +class MemoryCopyWriter : public MemoryWriter { public: + /*! @brief This constructor copies an existing buffer to write to. + * + * @param data The existing buffer + * @param length The length of the existing buffer + */ + explicit MemoryCopyWriter(atUint8* data = nullptr, atUint64 length = 0x10); - /*! @brief This constructor copies an existing buffer to write to. - * - * @param data The existing buffer - * @param length The length of the existing buffer - */ - explicit MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10); + /*! @brief This constructor creates an instance from a file on disk. + * + * @param filename The file to create the stream from + */ + MemoryCopyWriter(std::string_view filename); - /*! @brief This constructor creates an instance from a file on disk. - * - * @param filename The file to create the stream from - */ - MemoryCopyWriter(std::string_view filename); + /*! @brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * @param position where in the buffer to seek + * @param origin The Origin to seek @sa SeekOrigin + */ + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - /*! @brief Sets the buffers position relative to the specified position.
- * It seeks relative to the current position by default. - * @param position where in the buffer to seek - * @param origin The Origin to seek @sa SeekOrigin - */ - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + /*! @brief Sets the buffer to the given one, deleting the current one.
+ * BEWARE: As this deletes the current buffer it WILL cause a loss of data + * if that was not the intent.
+ * Once you pass the data to setData DO NOT delete the buffer + * as Stream now owns the address, this is done to keep memory usage down. + * @param data The new buffer. + * @param length The length of the new buffer. + * @throw IOException + */ + void setData(const atUint8* data, atUint64 length); - /*! @brief Sets the buffer to the given one, deleting the current one.
- * BEWARE: As this deletes the current buffer it WILL cause a loss of data - * if that was not the intent.
- * Once you pass the data to setData DO NOT delete the buffer - * as Stream now owns the address, this is done to keep memory usage down. - * @param data The new buffer. - * @param length The length of the new buffer. - * @throw IOException - */ - void setData(const atUint8* data, atUint64 length); - - /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length - * however it's undefined behavior to try and write a buffer which is smaller than the given length. - * - * @param data The buffer to write - * @param length The amount to write - */ - void writeUBytes(const atUint8* data, atUint64 len); + /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length + * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * + * @param data The buffer to write + * @param length The amount to write + */ + void writeUBytes(const atUint8* data, atUint64 len); protected: - std::unique_ptr m_dataCopy; + std::unique_ptr m_dataCopy; + private: - void resize(atUint64 newSize); + void resize(atUint64 newSize); }; -} - +} // namespace athena::io diff --git a/include/athena/PHYSFSFileReader.hpp b/include/athena/PHYSFSFileReader.hpp index 9f7d07e..6bdeecb 100644 --- a/include/athena/PHYSFSFileReader.hpp +++ b/include/athena/PHYSFSFileReader.hpp @@ -5,54 +5,51 @@ #include "athena/Stream.hpp" #include -namespace athena::io -{ -class PHYSFSFileReader : public Stream -{ +namespace athena::io { +class PHYSFSFileReader : public Stream { public: - PHYSFSFileReader(const std::string& path); + PHYSFSFileReader(const std::string& path); - void setEndian(Endian); - Endian endian() const; - bool isBigEndian() const; - bool isLittleEndian() const; - atUint8* data(); + void setEndian(Endian); + Endian endian() const; + bool isBigEndian() const; + bool isLittleEndian() const; + atUint8* data(); - atUint64 length() const; + atUint64 length() const; - atUint64 position() const; + atUint64 position() const; - bool isOpen() const; + bool isOpen() const; - void seek(atInt64 position, SeekOrigin origin); - atInt8 readByte(); - atUint8 readUByte(); - atUint8* readUBytes(atUint64 length); - atInt8* readBytes(atUint64 length); - atUint16 readUint16(); - atInt16 readInt16(); - atUint32 readUint32(); - atInt32 readInt32(); - atUint64 readUint64(); - atInt64 readInt64(); - double readDouble(); - float readFloat(); - bool readBool(); + void seek(atInt64 position, SeekOrigin origin); + atInt8 readByte(); + atUint8 readUByte(); + atUint8* readUBytes(atUint64 length); + atInt8* readBytes(atUint64 length); + atUint16 readUint16(); + atInt16 readInt16(); + atUint32 readUint32(); + atInt32 readInt32(); + atUint64 readUint64(); + atInt64 readInt64(); + double readDouble(); + float readFloat(); + bool readBool(); - bool atEnd() const; + bool atEnd() const; - // TODO: Strings + // TODO: Strings private: - Endian m_endian; - std::string m_path; - atUint64 m_length; - PHYSFS_File* m_handle; + Endian m_endian; + std::string m_path; + atUint64 m_length; + PHYSFS_File* m_handle; }; -} +} // namespace athena::io #ifndef PHYSFSFILEREADER_BASE -#define PHYSFSFILEREADER_BASE() \ - typedef athena::io::PHYSFSFileReader base +#define PHYSFSFILEREADER_BASE() typedef athena::io::PHYSFSFileReader base #endif #endif // PHYSFSSTREAM_HPP #endif // ATHENA_ENABLE_PHYSFS diff --git a/include/athena/SakuraGlobal.hpp b/include/athena/SakuraGlobal.hpp index a438233..7cc12f4 100644 --- a/include/athena/SakuraGlobal.hpp +++ b/include/athena/SakuraGlobal.hpp @@ -2,29 +2,18 @@ #include "athena/Global.hpp" -namespace athena::Sakura -{ +namespace athena::Sakura { template -class Vector2D -{ +class Vector2D { public: - T x; - T y; + T x; + T y; - Vector2D() - : x(0), - y(0) - { - } + Vector2D() : x(0), y(0) {} - Vector2D(T x, T y) - : x(x), - y(y) - { - } + Vector2D(T x, T y) : x(x), y(y) {} }; typedef Vector2D Vector2Di; typedef Vector2D Vector2Df; -} // Sakura - +} // namespace athena::Sakura diff --git a/include/athena/SkywardSwordFile.hpp b/include/athena/SkywardSwordFile.hpp index 4d94132..55b1303 100644 --- a/include/athena/SkywardSwordFile.hpp +++ b/include/athena/SkywardSwordFile.hpp @@ -5,43 +5,31 @@ // standard lib #include -namespace athena -{ +namespace athena { class SkywardSwordQuest; -enum class Region -{ - NTSC, - NTSCJ, - PAL -}; +enum class Region { NTSC, NTSCJ, PAL }; -class SkywardSwordFile -{ +class SkywardSwordFile { public: - enum MagicNumbers - { - USMagic = 0x534F5545, - JAMagic = 0x534F554A, - EUMagic = 0x534F5550 - }; + enum MagicNumbers { USMagic = 0x534F5545, JAMagic = 0x534F554A, EUMagic = 0x534F5550 }; - SkywardSwordFile(); - SkywardSwordFile(std::vector quests); - ~SkywardSwordFile(); + SkywardSwordFile(); + SkywardSwordFile(std::vector quests); + ~SkywardSwordFile(); - void addQuest(SkywardSwordQuest* q); - SkywardSwordQuest* quest(atUint32 id); - std::vector questList() const; + void addQuest(SkywardSwordQuest* q); + SkywardSwordQuest* quest(atUint32 id); + std::vector questList() const; - void setRegion(Region region); - Region region() const; + void setRegion(Region region); + Region region() const; private: - Region m_region; - // A vector is a bit overkill - std::vector m_quests; - atUint32 m_numQuests; + Region m_region; + // A vector is a bit overkill + std::vector m_quests; + atUint32 m_numQuests; }; -} +} // namespace athena diff --git a/include/athena/SkywardSwordFileReader.hpp b/include/athena/SkywardSwordFileReader.hpp index df05716..0b9e29d 100644 --- a/include/athena/SkywardSwordFileReader.hpp +++ b/include/athena/SkywardSwordFileReader.hpp @@ -2,19 +2,15 @@ #include "athena/MemoryReader.hpp" -namespace athena -{ +namespace athena { class SkywardSwordFile; -namespace io -{ -class SkywardSwordFileReader : public MemoryCopyReader -{ +namespace io { +class SkywardSwordFileReader : public MemoryCopyReader { public: - SkywardSwordFileReader(atUint8* data, atUint64 length); - SkywardSwordFileReader(const std::string& filename); + SkywardSwordFileReader(atUint8* data, atUint64 length); + SkywardSwordFileReader(const std::string& filename); - SkywardSwordFile* read(); + SkywardSwordFile* read(); }; -} // io -} // zelda - +} // namespace io +} // namespace athena diff --git a/include/athena/SkywardSwordFileWriter.hpp b/include/athena/SkywardSwordFileWriter.hpp index c83f318..a5437ea 100644 --- a/include/athena/SkywardSwordFileWriter.hpp +++ b/include/athena/SkywardSwordFileWriter.hpp @@ -2,20 +2,17 @@ #include "athena/MemoryWriter.hpp" -namespace athena -{ +namespace athena { class SkywardSwordFile; -namespace io -{ +namespace io { -class SkywardSwordFileWriter : public MemoryCopyWriter -{ +class SkywardSwordFileWriter : public MemoryCopyWriter { public: - SkywardSwordFileWriter(atUint8* data, atUint64 len); - SkywardSwordFileWriter(const std::string& filename); + SkywardSwordFileWriter(atUint8* data, atUint64 len); + SkywardSwordFileWriter(const std::string& filename); - void write(SkywardSwordFile* file); + void write(SkywardSwordFile* file); }; -} -} +} // namespace io +} // namespace athena diff --git a/include/athena/SkywardSwordQuest.hpp b/include/athena/SkywardSwordQuest.hpp index 618e69e..baaca14 100644 --- a/include/athena/SkywardSwordQuest.hpp +++ b/include/athena/SkywardSwordQuest.hpp @@ -4,55 +4,48 @@ #include "athena/Global.hpp" #include "athena/ZQuestFile.hpp" -namespace athena -{ +namespace athena { // TODO: Handle game specific data -class SkywardSwordQuest : public ZQuestFile -{ +class SkywardSwordQuest : public ZQuestFile { public: - enum AmmoType - { - Arrows, - Bombs, - Seeds - }; + enum AmmoType { Arrows, Bombs, Seeds }; - SkywardSwordQuest(std::unique_ptr&& data, atUint32 len); + SkywardSwordQuest(std::unique_ptr&& data, atUint32 len); - void setPlayerName(const std::string& name); - std::string playerName() const; + void setPlayerName(const std::string& name); + std::string playerName() const; - void setRupeeCount(atUint16 value); - atUint16 rupeeCount(); - void setAmmoCount(AmmoType type, atUint32 count); - atUint32 ammoCount(AmmoType type); - void setMaxHP(atUint16 val); - atUint16 maxHP(); - float maxHearts(); - void setSpawnHP(atUint16 val); - atUint16 spawnHP(); - float spawnHearts(); - void setCurrentHP(atUint16 val); - atUint16 currentHP(); - float currentHearts(); - std::string currentLocation(); - std::string currentArea(); - std::string currentLocationCopy(); + void setRupeeCount(atUint16 value); + atUint16 rupeeCount(); + void setAmmoCount(AmmoType type, atUint32 count); + atUint32 ammoCount(AmmoType type); + void setMaxHP(atUint16 val); + atUint16 maxHP(); + float maxHearts(); + void setSpawnHP(atUint16 val); + atUint16 spawnHP(); + float spawnHearts(); + void setCurrentHP(atUint16 val); + atUint16 currentHP(); + float currentHearts(); + std::string currentLocation(); + std::string currentArea(); + std::string currentLocationCopy(); - void setSkipData(std::unique_ptr&& data); - atUint8* skipData() const; + void setSkipData(std::unique_ptr&& data); + atUint8* skipData() const; - atUint32 slotChecksum(); - atUint32 skipChecksum(); - void fixChecksums(); + atUint32 slotChecksum(); + atUint32 skipChecksum(); + void fixChecksums(); - void setNew(bool isNew); - bool isNew() const; + void setNew(bool isNew); + bool isNew() const; private: - std::unique_ptr m_skipData; + std::unique_ptr m_skipData; }; -} // Athena +} // namespace athena #endif // SSQUEST_HPP diff --git a/include/athena/Socket.hpp b/include/athena/Socket.hpp index 08a814a..9570f03 100644 --- a/include/athena/Socket.hpp +++ b/include/athena/Socket.hpp @@ -14,89 +14,71 @@ typedef UINT_PTR SOCKET; struct sockaddr_in; -namespace athena::net -{ +namespace athena::net { /** IP address class derived from SFML */ -class IPAddress -{ - uint32_t m_address = 0; - bool m_valid = false; +class IPAddress { + uint32_t m_address = 0; + bool m_valid = false; - void resolve(const std::string& address); + void resolve(const std::string& address); public: - IPAddress(const std::string& address) - { - resolve(address); - } + IPAddress(const std::string& address) { resolve(address); } - uint32_t toInteger() const; - operator bool() const { return m_valid; } + uint32_t toInteger() const; + operator bool() const { return m_valid; } }; /** Server-oriented TCP socket class derived from SFML */ -class Socket -{ +class Socket { #ifndef _WIN32 - using SocketTp = int; + using SocketTp = int; #else - using SocketTp = SOCKET; + using SocketTp = SOCKET; #endif - SocketTp m_socket = -1; - bool m_isBlocking; + SocketTp m_socket = -1; + bool m_isBlocking; - bool openSocket(); - void setRemoteSocket(int remSocket); + bool openSocket(); + void setRemoteSocket(int remSocket); public: - enum class EResult - { - OK, - Error, - Busy - }; + enum class EResult { OK, Error, Busy }; #ifdef _WIN32 - static EResult LastWSAError(); + static EResult LastWSAError(); #endif - Socket(bool blocking) - : m_isBlocking(blocking) {} - ~Socket() { close(); } + Socket(bool blocking) : m_isBlocking(blocking) {} + ~Socket() { close(); } - Socket(const Socket& other) = delete; - Socket& operator=(const Socket& other) = delete; - Socket(Socket&& other) - : m_socket(other.m_socket), m_isBlocking(other.m_isBlocking) - { - other.m_socket = -1; - } - Socket& operator=(Socket&& other) - { - close(); - m_socket = other.m_socket; - other.m_socket = -1; - m_isBlocking = other.m_isBlocking; - return *this; - } + Socket(const Socket& other) = delete; + Socket& operator=(const Socket& other) = delete; + Socket(Socket&& other) : m_socket(other.m_socket), m_isBlocking(other.m_isBlocking) { other.m_socket = -1; } + Socket& operator=(Socket&& other) { + close(); + m_socket = other.m_socket; + other.m_socket = -1; + m_isBlocking = other.m_isBlocking; + return *this; + } - void setBlocking(bool blocking); - bool isOpen() const { return m_socket != -1; } - bool openAndListen(const IPAddress& address, uint32_t port); - EResult accept(Socket& remoteSocketOut, sockaddr_in& fromAddress); - EResult accept(Socket& remoteSocketOut); - EResult accept(Socket& remoteSocketOut, std::string& fromHostname); - void close(); - EResult send(const void* buf, size_t len, size_t& transferred); - EResult send(const void* buf, size_t len); - EResult recv(void* buf, size_t len, size_t& transferred); - EResult recv(void* buf, size_t len); + void setBlocking(bool blocking); + bool isOpen() const { return m_socket != -1; } + bool openAndListen(const IPAddress& address, uint32_t port); + EResult accept(Socket& remoteSocketOut, sockaddr_in& fromAddress); + EResult accept(Socket& remoteSocketOut); + EResult accept(Socket& remoteSocketOut, std::string& fromHostname); + void close(); + EResult send(const void* buf, size_t len, size_t& transferred); + EResult send(const void* buf, size_t len); + EResult recv(void* buf, size_t len, size_t& transferred); + EResult recv(void* buf, size_t len); - operator bool() const { return isOpen(); } + operator bool() const { return isOpen(); } - SocketTp GetInternalSocket() const { return m_socket; } + SocketTp GetInternalSocket() const { return m_socket; } }; -} - +} // namespace athena::net diff --git a/include/athena/Sprite.hpp b/include/athena/Sprite.hpp index ad92a76..47a32a4 100644 --- a/include/athena/Sprite.hpp +++ b/include/athena/Sprite.hpp @@ -4,67 +4,65 @@ #include #include "athena/SakuraGlobal.hpp" -namespace athena::Sakura -{ +namespace athena::Sakura { class SpriteFile; class SpriteFrame; -class Sprite -{ +class Sprite { public: - Sprite(SpriteFile* root); - Sprite(SpriteFile* root, const std::string& name); - virtual ~Sprite(); + Sprite(SpriteFile* root); + Sprite(SpriteFile* root, const std::string& name); + virtual ~Sprite(); - virtual void setPosition(const float x, const float y); - virtual void setPosition(const Vector2Df& pos); - virtual Vector2Df position() const; - void setName(const std::string& name); - std::string name() const; + virtual void setPosition(const float x, const float y); + virtual void setPosition(const Vector2Df& pos); + virtual Vector2Df position() const; + void setName(const std::string& name); + std::string name() const; - void addStateId(int id); + void addStateId(int id); - /*! - * \brief Returns the texture id of a given state - * \param index The index of the id. - * \return return the state id if it exists, -1 otherwise - */ - int stateId(int index) const; - void setStateIds(std::vector ids); - std::vector stateIds() const; - atUint32 stateCount() const; - void setCurrentState(atUint32 id); - atUint32 currentState() const; + /*! + * \brief Returns the texture id of a given state + * \param index The index of the id. + * \return return the state id if it exists, -1 otherwise + */ + int stateId(int index) const; + void setStateIds(std::vector ids); + std::vector stateIds() const; + atUint32 stateCount() const; + void setCurrentState(atUint32 id); + atUint32 currentState() const; - bool addFrame(SpriteFrame* Frame); - bool removeFrame(SpriteFrame* Frame); - SpriteFrame* Frame(atUint32 id); - void setFrame(atUint32 id); - void setFrames(std::vector frames); - atUint32 frameCount() const; + bool addFrame(SpriteFrame* Frame); + bool removeFrame(SpriteFrame* Frame); + SpriteFrame* Frame(atUint32 id); + void setFrame(atUint32 id); + void setFrames(std::vector frames); + atUint32 frameCount() const; - std::vector frames() const; + std::vector frames() const; - SpriteFile* container() const; + SpriteFile* container() const; - void setCurrentFrame(SpriteFrame* frame); - void setCurrentFrame(atUint32 id); - SpriteFrame* currentFrame() const; + void setCurrentFrame(SpriteFrame* frame); + void setCurrentFrame(atUint32 id); + SpriteFrame* currentFrame() const; - void advanceFrame(); - void retreatFrame(); + void advanceFrame(); + void retreatFrame(); + + void setRoot(SpriteFile* root); + SpriteFile* root() const; - void setRoot(SpriteFile* root); - SpriteFile* root() const; private: - SpriteFile* m_root; - std::string m_name; - Vector2Df m_position; - std::vector m_stateIds; //!< Stores the texture id's for each state. - std::vector m_frames; - atUint32 m_currentState; - atUint32 m_currentFrame; + SpriteFile* m_root; + std::string m_name; + Vector2Df m_position; + std::vector m_stateIds; //!< Stores the texture id's for each state. + std::vector m_frames; + atUint32 m_currentState; + atUint32 m_currentFrame; }; -} // zelda - +} // namespace athena::Sakura diff --git a/include/athena/SpriteFile.hpp b/include/athena/SpriteFile.hpp index dd2e9eb..6efce4a 100644 --- a/include/athena/SpriteFile.hpp +++ b/include/athena/SpriteFile.hpp @@ -7,74 +7,71 @@ #include #include "athena/SakuraGlobal.hpp" -namespace athena::Sakura -{ -struct STexture -{ - std::string Filepath; - bool Preload; +namespace athena::Sakura { +struct STexture { + std::string Filepath; + bool Preload; }; class Sprite; -class SpriteFile -{ +class SpriteFile { public: - /*! - * \brief Major - */ - static const atUint32 Major; + /*! + * \brief Major + */ + static const atUint32 Major; - /*! - * \brief Minor - */ - static const atUint32 Minor; + /*! + * \brief Minor + */ + static const atUint32 Minor; - /*! - * \brief Revision - */ - static const atUint32 Revision; + /*! + * \brief Revision + */ + static const atUint32 Revision; - /*! - * \brief Patch - */ - static const atUint32 Build; + /*! + * \brief Patch + */ + static const atUint32 Build; - /*! - * \brief Version - */ - static const atUint32 Version; + /*! + * \brief Version + */ + static const atUint32 Version; - /*! - * \brief Magic - */ - static const atUint32 Magic; + /*! + * \brief Magic + */ + static const atUint32 Magic; - /*! - * \brief SSprite - */ - SpriteFile(); + /*! + * \brief SSprite + */ + SpriteFile(); - /*! - * \brief SSpriteFile - * \param width - * \param height - * \param originX - * \param originY - */ - SpriteFile(atUint32 width, atUint32 height, float originX, float originY); + /*! + * \brief SSpriteFile + * \param width + * \param height + * \param originX + * \param originY + */ + SpriteFile(atUint32 width, atUint32 height, float originX, float originY); - /*! - * \brief SSpriteFile - * \param size - * \param origin - */ + /*! + * \brief SSpriteFile + * \param size + * \param origin + */ #ifndef ATHENA_USE_QT - SpriteFile(const Vector2Di& size, const Vector2Df& origin); + SpriteFile(const Vector2Di& size, const Vector2Df& origin); #else - SpriteFile(const QSize& size, const QPoint& origin); + SpriteFile(const QSize& size, const QPoint& origin); #endif - ~SpriteFile(); + ~SpriteFile(); #ifndef ATHENA_USE_QT public: @@ -82,113 +79,112 @@ public: public slots: #endif - /*! - * \brief setSize - * \param width - * \param height - */ - void setSize(atUint32 width, atUint32 height); + /*! + * \brief setSize + * \param width + * \param height + */ + void setSize(atUint32 width, atUint32 height); - /*! - * \brief setSize - * \param size - */ - void setSize(const Vector2Di& size); + /*! + * \brief setSize + * \param size + */ + void setSize(const Vector2Di& size); - /*! - * \brief size - * \return - */ - Vector2Di size() const; + /*! + * \brief size + * \return + */ + Vector2Di size() const; - /*! - * \brief width - * \return - */ - atUint32 width() const; + /*! + * \brief width + * \return + */ + atUint32 width() const; - /*! - * \brief height - * \return - */ - atUint32 height() const; + /*! + * \brief height + * \return + */ + atUint32 height() const; - /*! - * \brief setOrigin - * \param x - * \param y - */ - void setOrigin(const float x, const float y); + /*! + * \brief setOrigin + * \param x + * \param y + */ + void setOrigin(const float x, const float y); - /*! - * \brief setOrigin - * \param origin - */ - void setOrigin(const Vector2Df& origin); + /*! + * \brief setOrigin + * \param origin + */ + void setOrigin(const Vector2Df& origin); - /*! - * \brief origin - * \return - */ - Vector2Df origin() const; + /*! + * \brief origin + * \return + */ + Vector2Df origin() const; + /*! + * \brief originX + * \return + */ + float originX() const; - /*! - * \brief originX - * \return - */ - float originX() const; + /*! + * \brief originY + * \return + */ + float originY() const; - /*! - * \brief originY - * \return - */ - float originY() const; + /*! + * \brief addTexture + * \param texture + */ + bool addTexture(STexture* texture); - /*! - * \brief addTexture - * \param texture - */ - bool addTexture(STexture* texture); + /*! + * \brief removeTexture + * \param id + */ + void removeTexture(int id); - /*! - * \brief removeTexture - * \param id - */ - void removeTexture(int id); + /*! + * \brief texture + * \param id + * \return + */ + STexture* texture(atUint32 id); + std::vector textures() const; - /*! - * \brief texture - * \param id - * \return - */ - STexture* texture(atUint32 id); - std::vector textures() const; + atUint32 textureCount() const; + /*! + * \brief setTextures + * \param textures + */ + void setTextures(std::vector textures); - atUint32 textureCount() const; - /*! - * \brief setTextures - * \param textures - */ - void setTextures(std::vector textures); + void addSprite(Sprite* sprite); - void addSprite(Sprite* sprite); + void removeSprite(const std::string& name); + void removeSprite(Sprite* sprite); - void removeSprite(const std::string& name); - void removeSprite(Sprite* sprite); + void setSprites(std::unordered_map sprites); + Sprite* sprite(const std::string& name); + std::unordered_map sprites() const; - void setSprites(std::unordered_map sprites); - Sprite* sprite(const std::string& name); - std::unordered_map sprites() const; - - atUint32 spriteCount() const; + atUint32 spriteCount() const; private: - std::vector m_textures; - Vector2Di m_size; - Vector2Df m_origin; - std::unordered_map m_sprites; + std::vector m_textures; + Vector2Di m_size; + Vector2Df m_origin; + std::unordered_map m_sprites; }; -} // Zelda +} // namespace athena::Sakura #endif // SSPRITE_HPP diff --git a/include/athena/SpriteFileReader.hpp b/include/athena/SpriteFileReader.hpp index 6c106ae..e9d35c7 100644 --- a/include/athena/SpriteFileReader.hpp +++ b/include/athena/SpriteFileReader.hpp @@ -2,25 +2,19 @@ #include "athena/MemoryReader.hpp" -namespace athena::Sakura -{ +namespace athena::Sakura { class SpriteFile; -} // Sakura +} // namespace athena::Sakura -namespace athena -{ -namespace io -{ +namespace athena { +namespace io { -class SpriteFileReader : public MemoryCopyReader -{ +class SpriteFileReader : public MemoryCopyReader { public: - SpriteFileReader(atUint8* data, atUint64 length); - SpriteFileReader(const std::string& filepath); + SpriteFileReader(atUint8* data, atUint64 length); + SpriteFileReader(const std::string& filepath); - Sakura::SpriteFile* readFile(); + Sakura::SpriteFile* readFile(); }; -} -} // zelda - - +} // namespace io +} // namespace athena diff --git a/include/athena/SpriteFileWriter.hpp b/include/athena/SpriteFileWriter.hpp index d7b749f..7b9b4e3 100644 --- a/include/athena/SpriteFileWriter.hpp +++ b/include/athena/SpriteFileWriter.hpp @@ -2,25 +2,21 @@ #include "athena/MemoryWriter.hpp" -namespace athena -{ -namespace Sakura -{ +namespace athena { +namespace Sakura { class SpriteFile; -} // Sakura +} // namespace Sakura -namespace io -{ +namespace io { -class SpriteFileWriter : public MemoryCopyWriter -{ +class SpriteFileWriter : public MemoryCopyWriter { public: - SpriteFileWriter(atUint8* data, atUint64 length); + SpriteFileWriter(atUint8* data, atUint64 length); - SpriteFileWriter(std::string_view filepath); + SpriteFileWriter(std::string_view filepath); - void writeFile(Sakura::SpriteFile* file); + void writeFile(Sakura::SpriteFile* file); }; -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/include/athena/SpriteFrame.hpp b/include/athena/SpriteFrame.hpp index a391a4b..d390658 100644 --- a/include/athena/SpriteFrame.hpp +++ b/include/athena/SpriteFrame.hpp @@ -1,49 +1,45 @@ #pragma once - #include "athena/SakuraGlobal.hpp" #include -namespace athena::Sakura -{ +namespace athena::Sakura { class Sprite; class SpritePart; -class SpriteFrame -{ +class SpriteFrame { public: - /*! - * \brief SSpriteFrame - */ - SpriteFrame(); + /*! + * \brief SSpriteFrame + */ + SpriteFrame(); - SpriteFrame(Sprite* root); - /*! - * \brief setFrameTime - * \param frameTime - */ - void setFrameTime(float frameTime); + SpriteFrame(Sprite* root); + /*! + * \brief setFrameTime + * \param frameTime + */ + void setFrameTime(float frameTime); + /*! + * \brief frameTime + * \return + */ + float frameTime() const; - /*! - * \brief frameTime - * \return - */ - float frameTime() const; + void setParts(std::vector parts); + std::vector parts() const; - void setParts(std::vector parts); - std::vector parts() const; + atUint32 partCount() const; - atUint32 partCount() const; + void setRoot(Sprite* root); + Sprite* root() const; - void setRoot(Sprite* root); - Sprite* root() const; private: - Sprite* m_root; - float m_frameTime; - std::vector m_parts; + Sprite* m_root; + float m_frameTime; + std::vector m_parts; }; -} // zelda - +} // namespace athena::Sakura diff --git a/include/athena/SpritePart.hpp b/include/athena/SpritePart.hpp index e98f580..2c39341 100644 --- a/include/athena/SpritePart.hpp +++ b/include/athena/SpritePart.hpp @@ -5,110 +5,106 @@ #include -namespace athena::Sakura -{ +namespace athena::Sakura { class SpriteFrame; -class SpritePart -{ +class SpritePart { public: - SpritePart(SpriteFrame* root); - SpritePart(SpriteFrame* root, const std::string& name, bool hasCollision = false); - virtual ~SpritePart(); + SpritePart(SpriteFrame* root); + SpritePart(SpriteFrame* root, const std::string& name, bool hasCollision = false); + virtual ~SpritePart(); - void setName(const std::string& name); - std::string name() const; - void setCollision(bool col); - bool hasCollision() const; + void setName(const std::string& name); + std::string name() const; + void setCollision(bool col); + bool hasCollision() const; - /*! - * \brief setOffset - * \param x - * \param y - */ - void setOffset(float x, float y); - void setOffset(const Vector2Df& offset); + /*! + * \brief setOffset + * \param x + * \param y + */ + void setOffset(float x, float y); + void setOffset(const Vector2Df& offset); - /*! - * \brief offset - * \return - */ - Vector2Df offset() const; + /*! + * \brief offset + * \return + */ + Vector2Df offset() const; - /*! - * \brief setTextureOffset - * \param x - * \param y - */ - void setTextureOffset(float x, float y); + /*! + * \brief setTextureOffset + * \param x + * \param y + */ + void setTextureOffset(float x, float y); - /*! - * \brief setTextureOffset - * \param texOff - */ - void setTextureOffset(const Vector2Df& offset); + /*! + * \brief setTextureOffset + * \param texOff + */ + void setTextureOffset(const Vector2Df& offset); -/*! - * \brief textureOffset - * \return - */ - Vector2Df textureOffset() const; - /*! - * \brief setSize - * \param width - * \param height - */ - void setSize(atUint32 width, atUint32 height); + /*! + * \brief textureOffset + * \return + */ + Vector2Df textureOffset() const; + /*! + * \brief setSize + * \param width + * \param height + */ + void setSize(atUint32 width, atUint32 height); -/*! - * \brief setSize - * \param size - */ - void setSize(const Vector2Di& size); -/*! - * \brief size - * \return - */ - Vector2Di size() const; + /*! + * \brief setSize + * \param size + */ + void setSize(const Vector2Di& size); + /*! + * \brief size + * \return + */ + Vector2Di size() const; - /*! - * \brief setFlippedHorizontally - * \param val - */ - void setFlippedHorizontally(const bool val); + /*! + * \brief setFlippedHorizontally + * \param val + */ + void setFlippedHorizontally(const bool val); - /*! - * \brief flippedHorizontally - * \return - */ - bool flippedHorizontally() const; + /*! + * \brief flippedHorizontally + * \return + */ + bool flippedHorizontally() const; - /*! - * \brief setFlippedVertically - * \param val - */ - void setFlippedVertically(const bool val); + /*! + * \brief setFlippedVertically + * \param val + */ + void setFlippedVertically(const bool val); - /*! - * \brief flippedVertically - * \return - */ - bool flippedVertically() const; - - void setRoot(SpriteFrame* root); - SpriteFrame* root() const; + /*! + * \brief flippedVertically + * \return + */ + bool flippedVertically() const; + void setRoot(SpriteFrame* root); + SpriteFrame* root() const; private: - SpriteFrame* m_root; - std::string m_name; - bool m_hasCollision; - Vector2Df m_offset; - Vector2Df m_textureOffset; - Vector2Di m_size; - bool m_flippedH; - bool m_flippedV; - atUint32 m_frameIndex; + SpriteFrame* m_root; + std::string m_name; + bool m_hasCollision; + Vector2Df m_offset; + Vector2Df m_textureOffset; + Vector2Di m_size; + bool m_flippedH; + bool m_flippedV; + atUint32 m_frameIndex; }; -} - +} // namespace athena::Sakura diff --git a/include/athena/Types.hpp b/include/athena/Types.hpp index e54a4f6..a7b6cac 100644 --- a/include/athena/Types.hpp +++ b/include/athena/Types.hpp @@ -13,23 +13,34 @@ using atUint64 = uint64_t; // Vector types #include "simd/simd.hpp" -typedef struct { athena::simd simd; } atVec2f; -typedef struct { athena::simd simd; } atVec3f; -typedef struct { athena::simd simd; } atVec4f; -typedef struct { athena::simd simd; } atVec2d; -typedef struct { athena::simd simd; } atVec3d; -typedef struct { athena::simd simd; } atVec4d; +typedef struct { + athena::simd simd; +} atVec2f; +typedef struct { + athena::simd simd; +} atVec3f; +typedef struct { + athena::simd simd; +} atVec4f; +typedef struct { + athena::simd simd; +} atVec2d; +typedef struct { + athena::simd simd; +} atVec3d; +typedef struct { + athena::simd simd; +} atVec4d; #ifndef UNUSED #define UNUSED(x) ((void)x) #endif // UNUSED #ifdef __GNUC__ -#define DEPRECATED(func) func __attribute__ ((deprecated)) +#define DEPRECATED(func) func __attribute__((deprecated)) #elif defined(_MSC_VER) #define DEPRECATED(func) __declspec(deprecated) func #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED(func) func #endif - diff --git a/include/athena/Utility.hpp b/include/athena/Utility.hpp index c3b5d06..f311679 100644 --- a/include/athena/Utility.hpp +++ b/include/athena/Utility.hpp @@ -9,190 +9,165 @@ #include "athena/Global.hpp" #include "athena/Types.hpp" -namespace athena::utility -{ -inline bool isEmpty(atInt8* buf, atUint32 size) {return !memcmp(buf, buf + 1, size - 1);} +namespace athena::utility { +inline bool isEmpty(atInt8* buf, atUint32 size) { return !memcmp(buf, buf + 1, size - 1); } #if _WIN32 -constexpr bool isSystemBigEndian() {return false;} +constexpr bool isSystemBigEndian() { return false; } #else -constexpr bool isSystemBigEndian() {return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;} +constexpr bool isSystemBigEndian() { return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; } #endif inline constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? Big : Little; inline constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? Little : Big; -inline atInt16 swap16(atInt16 val) -{ +inline atInt16 swap16(atInt16 val) { #if __GNUC__ - return __builtin_bswap16(val); + return __builtin_bswap16(val); #elif _WIN32 - return _byteswap_ushort(val); + return _byteswap_ushort(val); #else - return (val = (val << 8) | ((val >> 8) & 0xFF)); + return (val = (val << 8) | ((val >> 8) & 0xFF)); #endif } -inline atUint16 swapU16(atUint16 val) {return (atUint16)swap16(val);} -inline atInt32 swap32(atInt32 val) -{ +inline atUint16 swapU16(atUint16 val) { return (atUint16)swap16(val); } +inline atInt32 swap32(atInt32 val) { #if __GNUC__ - return __builtin_bswap32(val); + return __builtin_bswap32(val); #elif _WIN32 - return _byteswap_ulong(val); + return _byteswap_ulong(val); #else - val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; - val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8; - return val; + val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; + val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8; + return val; #endif } -inline atUint32 swapU32(atUint32 val) {return (atUint32)swap32(val);} -inline atInt64 swap64(atInt64 val) -{ +inline atUint32 swapU32(atUint32 val) { return (atUint32)swap32(val); } +inline atInt64 swap64(atInt64 val) { #if __GNUC__ - return __builtin_bswap64(val); + return __builtin_bswap64(val); #elif _WIN32 - return _byteswap_uint64(val); + return _byteswap_uint64(val); #else - return (val = ((atInt64)((((atInt64)(val) & 0xFF00000000000000ULL) >> 56) | - (((atInt64)(val) & 0x00FF000000000000ULL) >> 40) | - (((atInt64)(val) & 0x0000FF0000000000ULL) >> 24) | - (((atInt64)(val) & 0x000000FF00000000ULL) >> 8) | - (((atInt64)(val) & 0x00000000FF000000ULL) << 8) | - (((atInt64)(val) & 0x0000000000FF0000ULL) << 24) | - (((atInt64)(val) & 0x000000000000FF00ULL) << 40) | - (((atInt64)(val) & 0x00000000000000FFULL) << 56)))); + return (val = ((atInt64)( + (((atInt64)(val)&0xFF00000000000000ULL) >> 56) | (((atInt64)(val)&0x00FF000000000000ULL) >> 40) | + (((atInt64)(val)&0x0000FF0000000000ULL) >> 24) | (((atInt64)(val)&0x000000FF00000000ULL) >> 8) | + (((atInt64)(val)&0x00000000FF000000ULL) << 8) | (((atInt64)(val)&0x0000000000FF0000ULL) << 24) | + (((atInt64)(val)&0x000000000000FF00ULL) << 40) | (((atInt64)(val)&0x00000000000000FFULL) << 56)))); #endif } -inline atUint64 swapU64(atUint64 val) {return (atUint64)swap64(val);} -inline float swapFloat(float val) -{ - atInt32 ival = swap32(*((atInt32*)(&val))); - return *((float*)(&ival)); +inline atUint64 swapU64(atUint64 val) { return (atUint64)swap64(val); } +inline float swapFloat(float val) { + atInt32 ival = swap32(*((atInt32*)(&val))); + return *((float*)(&ival)); } -inline double swapDouble(double val) -{ - atInt64 ival = swap64(*((atInt64*)(&val))); - return *((double*)(&ival)); +inline double swapDouble(double val) { + atInt64 ival = swap64(*((atInt64*)(&val))); + return *((double*)(&ival)); } -inline atInt16 LittleInt16(atInt16& val) -{ - if (athena::utility::isSystemBigEndian()) - val = athena::utility::swap16(val); +inline atInt16 LittleInt16(atInt16& val) { + if (athena::utility::isSystemBigEndian()) + val = athena::utility::swap16(val); - return val; + return val; } -inline atUint16 LittleUint16(atUint16& val) -{ - atInt16 ret = val; - LittleInt16(ret); - val = ret; +inline atUint16 LittleUint16(atUint16& val) { + atInt16 ret = val; + LittleInt16(ret); + val = ret; - return val; + return val; } -inline atInt16 BigInt16(atInt16& val) -{ - if (!athena::utility::isSystemBigEndian()) - val = athena::utility::swap16(val); +inline atInt16 BigInt16(atInt16& val) { + if (!athena::utility::isSystemBigEndian()) + val = athena::utility::swap16(val); - return val; + return val; } -inline atUint16 BigUint16(atUint16& val) -{ - atInt16 ret = val; - BigInt16(ret); - val = ret; +inline atUint16 BigUint16(atUint16& val) { + atInt16 ret = val; + BigInt16(ret); + val = ret; - return val; + return val; } -inline atInt32 LittleInt32(atInt32& val) -{ - if (athena::utility::isSystemBigEndian()) - val = athena::utility::swap32(val); +inline atInt32 LittleInt32(atInt32& val) { + if (athena::utility::isSystemBigEndian()) + val = athena::utility::swap32(val); - return val; + return val; } -inline atUint32 LittleUint32(atUint32& val) -{ - atInt32 ret = val; - LittleInt32(ret); - val = ret; +inline atUint32 LittleUint32(atUint32& val) { + atInt32 ret = val; + LittleInt32(ret); + val = ret; - return val; + return val; } -inline atInt32 BigInt32(atInt32& val) -{ - if (!athena::utility::isSystemBigEndian()) - val = athena::utility::swap32(val); +inline atInt32 BigInt32(atInt32& val) { + if (!athena::utility::isSystemBigEndian()) + val = athena::utility::swap32(val); - return val; + return val; } -inline atUint32 BigUint32(atUint32& val) -{ - atInt32 ret = val; - BigInt32(ret); - val = ret; +inline atUint32 BigUint32(atUint32& val) { + atInt32 ret = val; + BigInt32(ret); + val = ret; - return val; + return val; } -inline atInt64 LittleInt64(atInt64& val) -{ - if (athena::utility::isSystemBigEndian()) - val = athena::utility::swap64(val); +inline atInt64 LittleInt64(atInt64& val) { + if (athena::utility::isSystemBigEndian()) + val = athena::utility::swap64(val); - return val; + return val; } -inline atUint64 LittleUint64(atUint64& val) -{ - atInt64 ret = val; - LittleInt64(ret); - val = ret; +inline atUint64 LittleUint64(atUint64& val) { + atInt64 ret = val; + LittleInt64(ret); + val = ret; - return val; + return val; } -inline atInt64 BigInt64(atInt64& val) -{ - if (!athena::utility::isSystemBigEndian()) - val = athena::utility::swap64(val); +inline atInt64 BigInt64(atInt64& val) { + if (!athena::utility::isSystemBigEndian()) + val = athena::utility::swap64(val); - return val; + return val; } -inline atUint64 BigUint64(atUint64& val) -{ - atInt64 ret = val; - BigInt64(ret); - val = ret; +inline atUint64 BigUint64(atUint64& val) { + atInt64 ret = val; + BigInt64(ret); + val = ret; - return val; + return val; } -inline float LittleFloat(float val) -{ - if (athena::utility::isSystemBigEndian()) - val = athena::utility::swapFloat(val); +inline float LittleFloat(float val) { + if (athena::utility::isSystemBigEndian()) + val = athena::utility::swapFloat(val); - return val; + return val; } -inline float BigFloat(float val) -{ - if (!athena::utility::isSystemBigEndian()) - val = athena::utility::swapFloat(val); +inline float BigFloat(float val) { + if (!athena::utility::isSystemBigEndian()) + val = athena::utility::swapFloat(val); - return val; + return val; } -inline double LittleDouble(double val) -{ - if (athena::utility::isSystemBigEndian()) - val = athena::utility::swapDouble(val); +inline double LittleDouble(double val) { + if (athena::utility::isSystemBigEndian()) + val = athena::utility::swapDouble(val); - return val; + return val; } -inline double BigDouble(double val) -{ - if (!athena::utility::isSystemBigEndian()) - val = athena::utility::swapDouble(val); +inline double BigDouble(double val) { + if (!athena::utility::isSystemBigEndian()) + val = athena::utility::swapDouble(val); - return val; + return val; } -void fillRandom(atUint8 * rndArea, atUint64 count); +void fillRandom(atUint8* rndArea, atUint64 count); std::vector split(std::string_view s, char delim); atUint64 rand64(); std::string join(const std::vector& elems, std::string_view delims); @@ -221,5 +196,5 @@ std::string wideToUtf8(std::wstring_view src); std::wstring utf8ToWide(std::string_view src); -} // Athena +} // namespace athena::utility #endif diff --git a/include/athena/VectorWriter.hpp b/include/athena/VectorWriter.hpp index 519d96b..f17e160 100644 --- a/include/athena/VectorWriter.hpp +++ b/include/athena/VectorWriter.hpp @@ -6,8 +6,7 @@ #include #include "athena/IStreamWriter.hpp" -namespace athena::io -{ +namespace athena::io { /*! @class VectorWriter * @brief A Stream class for writing data to a STL vector @@ -16,46 +15,44 @@ namespace athena::io * all work is done using a std::vector, and not written directly to the disk * @sa Stream */ -class VectorWriter : public IStreamWriter -{ +class VectorWriter : public IStreamWriter { public: - /*! @brief Sets the buffers position relative to the specified position.
- * It seeks relative to the current position by default. - * @param position where in the buffer to seek - * @param origin The Origin to seek @sa SeekOrigin - */ - void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); + /*! @brief Sets the buffers position relative to the specified position.
+ * It seeks relative to the current position by default. + * @param position where in the buffer to seek + * @param origin The Origin to seek @sa SeekOrigin + */ + void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - /*! @brief Returns the current position in the stream. - * - * @return Int64 The current position in the stream. - */ - inline atUint64 position() const { return m_position; } + /*! @brief Returns the current position in the stream. + * + * @return Int64 The current position in the stream. + */ + inline atUint64 position() const { return m_position; } - /*! @brief Returns the length of the stream. - * - * @return Int64 The length of the stream. - */ - inline atUint64 length() const { return m_data.size(); } + /*! @brief Returns the length of the stream. + * + * @return Int64 The length of the stream. + */ + inline atUint64 length() const { return m_data.size(); } - inline bool isOpen() const { return true; } + inline bool isOpen() const { return true; } - /*! @brief Obtains reference to underlying std::vector store */ - const std::vector& data() const { return m_data; } + /*! @brief Obtains reference to underlying std::vector store */ + const std::vector& data() const { return m_data; } - /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length - * however it's undefined behavior to try and write a buffer which is smaller than the given length. - * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. - * - * @param data The buffer to write - * @param length The amount to write - */ - void writeUBytes(const atUint8* data, atUint64 len); + /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length + * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. + * + * @param data The buffer to write + * @param length The amount to write + */ + void writeUBytes(const atUint8* data, atUint64 len); protected: - std::vector m_data; - atUint64 m_position = 0; + std::vector m_data; + atUint64 m_position = 0; }; -} - +} // namespace athena::io diff --git a/include/athena/WiiBanner.hpp b/include/athena/WiiBanner.hpp index f248b41..e4faaf2 100644 --- a/include/athena/WiiBanner.hpp +++ b/include/athena/WiiBanner.hpp @@ -4,172 +4,165 @@ #include #include "athena/Global.hpp" -namespace athena -{ +namespace athena { class WiiImage; /*! \class WiiBanner * \brief Wii banner container class * * Contains all relevant data for a Wii banner. */ -class WiiBanner -{ +class WiiBanner { public: - enum - { - NoCopy = 0x00000001, - Bounce = 0x00000010, - NoCopyBounce = NoCopy | Bounce - }; + enum { NoCopy = 0x00000001, Bounce = 0x00000010, NoCopyBounce = NoCopy | Bounce }; - /*! - * \brief WiiBanner - */ - WiiBanner(); - /*! - * \brief WiiBanner - * \param gameId - * \param title - * \param subtitle - * \param m_banner - * \param icons - */ - WiiBanner(atUint32 gameId, const std::u16string& title, const std::u16string& subtitle, - WiiImage* m_banner, std::vector icons); - virtual ~WiiBanner(); + /*! + * \brief WiiBanner + */ + WiiBanner(); + /*! + * \brief WiiBanner + * \param gameId + * \param title + * \param subtitle + * \param m_banner + * \param icons + */ + WiiBanner(atUint32 gameId, const std::u16string& title, const std::u16string& subtitle, WiiImage* m_banner, + std::vector icons); + virtual ~WiiBanner(); - /*! - * \brief setGameID - * \param id - */ - void setGameID(atUint64 id); + /*! + * \brief setGameID + * \param id + */ + void setGameID(atUint64 id); - /*! - * \brief gameID - * \return - */ - atUint64 gameID() const; + /*! + * \brief gameID + * \return + */ + atUint64 gameID() const; - /*! - * \brief setBannerImage - * \param banner - */ - void setBannerImage(WiiImage* banner); + /*! + * \brief setBannerImage + * \param banner + */ + void setBannerImage(WiiImage* banner); - /*! - * \brief bannerImage - * \return - */ - WiiImage* bannerImage() const; + /*! + * \brief bannerImage + * \return + */ + WiiImage* bannerImage() const; - /*! - * \brief setBannerSize - * \param size - */ - void setBannerSize(atUint32 size); + /*! + * \brief setBannerSize + * \param size + */ + void setBannerSize(atUint32 size); - /*! - * \brief bannerSize - * \return - */ - atUint32 bannerSize() const; + /*! + * \brief bannerSize + * \return + */ + atUint32 bannerSize() const; - /*! - * \brief setTitle - * \param title - */ - void setTitle(const std::u16string& title); + /*! + * \brief setTitle + * \param title + */ + void setTitle(const std::u16string& title); - /*! - * \brief title - * \return - */ - const std::u16string& title() const; + /*! + * \brief title + * \return + */ + const std::u16string& title() const; - /*! - * \brief setSubtitle - * \param subtitle - */ - void setSubtitle(const std::u16string& subtitle); + /*! + * \brief setSubtitle + * \param subtitle + */ + void setSubtitle(const std::u16string& subtitle); - /*! - * \brief subtitle - * \return - */ - const std::u16string& subtitle() const; + /*! + * \brief subtitle + * \return + */ + const std::u16string& subtitle() const; - /*! - * \brief addIcon - * \param icon - */ - void addIcon(WiiImage* icon); + /*! + * \brief addIcon + * \param icon + */ + void addIcon(WiiImage* icon); - /*! - * \brief setIcon - * \param id - * \param icon - */ - void setIcon(atUint32 id, WiiImage* icon); + /*! + * \brief setIcon + * \param id + * \param icon + */ + void setIcon(atUint32 id, WiiImage* icon); - /*! - * \brief getIcon - * \param id - * \return - */ - WiiImage* getIcon(atUint32 id) const; + /*! + * \brief getIcon + * \param id + * \return + */ + WiiImage* getIcon(atUint32 id) const; - /*! - * \brief icons - * \return - */ - std::vector icons() const; + /*! + * \brief icons + * \return + */ + std::vector icons() const; - /*! - * \brief setAnimationSpeed - * \param animSpeed - */ - void setAnimationSpeed(atUint16 animSpeed); + /*! + * \brief setAnimationSpeed + * \param animSpeed + */ + void setAnimationSpeed(atUint16 animSpeed); - /*! - * \brief animationSpeed - * \return - */ - atUint16 animationSpeed() const; + /*! + * \brief animationSpeed + * \return + */ + atUint16 animationSpeed() const; - /*! - * \brief setPermissions - * \param permissions - */ - void setPermissions(atUint8 permissions); + /*! + * \brief setPermissions + * \param permissions + */ + void setPermissions(atUint8 permissions); - /*! - * \brief permissions - * \return - */ - atUint8 permissions() const; + /*! + * \brief permissions + * \return + */ + atUint8 permissions() const; - /*! - * \brief setFlags - * \param flags - */ - void setFlags(atUint32 flags); + /*! + * \brief setFlags + * \param flags + */ + void setFlags(atUint32 flags); + + /*! + * \brief flags + * \return + */ + atUint32 flags() const; - /*! - * \brief flags - * \return - */ - atUint32 flags() const; protected: private: - atUint64 m_gameId; - WiiImage* m_banner; - atUint32 m_animSpeed; - atUint8 m_permissions; - atUint32 m_flags; - atUint32 m_bannerSize; - std::vector m_icons; - std::u16string m_title; - std::u16string m_subtitle; + atUint64 m_gameId; + WiiImage* m_banner; + atUint32 m_animSpeed; + atUint8 m_permissions; + atUint32 m_flags; + atUint32 m_bannerSize; + std::vector m_icons; + std::u16string m_title; + std::u16string m_subtitle; }; -} // zelda - +} // namespace athena diff --git a/include/athena/WiiFile.hpp b/include/athena/WiiFile.hpp index fa38b1e..fa34ce0 100644 --- a/include/athena/WiiFile.hpp +++ b/include/athena/WiiFile.hpp @@ -5,217 +5,213 @@ #include #include "athena/Global.hpp" -namespace athena -{ +namespace athena { -const atUint8 SD_KEY [16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d}; -const atUint8 SD_IV [16] = {0x21, 0x67, 0x12, 0xe6, 0xaa, 0x1f, 0x68, 0x9f, 0x95, 0xc5, 0xa2, 0x23, 0x24, 0xdc, 0x6a, 0x98}; -const atUint8 MD5_BLANKER[16] = {0x0e, 0x65, 0x37, 0x81, 0x99, 0xbe, 0x45, 0x17, 0xab, 0x06, 0xec, 0x22, 0x45, 0x1a, 0x57, 0x93}; +const atUint8 SD_KEY[16] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, + 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d}; +const atUint8 SD_IV[16] = {0x21, 0x67, 0x12, 0xe6, 0xaa, 0x1f, 0x68, 0x9f, + 0x95, 0xc5, 0xa2, 0x23, 0x24, 0xdc, 0x6a, 0x98}; +const atUint8 MD5_BLANKER[16] = {0x0e, 0x65, 0x37, 0x81, 0x99, 0xbe, 0x45, 0x17, + 0xab, 0x06, 0xec, 0x22, 0x45, 0x1a, 0x57, 0x93}; /*! \class WiiFile * \brief Wii file container class * * Contains all relevant data for a file in a data.bin file. */ -class WiiFile -{ +class WiiFile { public: + /*! \enum Permission + * \brief The Wii uses a bastardized unix permissions system so these flags + * reflect the file's individual permissions. + */ + enum Permission { + OtherRead = 0x01, + OtherWrite = 0x02, + GroupRead = 0x04, + GroupWrite = 0x08, + OwnerRead = 0x10, + OwnerWrite = 0x20, - /*! \enum Permission - * \brief The Wii uses a bastardized unix permissions system so these flags - * reflect the file's individual permissions. - */ - enum Permission - { - OtherRead = 0x01, - OtherWrite = 0x02, - GroupRead = 0x04, - GroupWrite = 0x08, - OwnerRead = 0x10, - OwnerWrite = 0x20, + // Mask values; + OtherRW = (OtherRead | OtherWrite), //!< Mask to get the Other group permissions + GroupRW = (GroupRead | GroupWrite), + OwnerRW = (OwnerRead | OwnerWrite) + }; - // Mask values; - OtherRW = (OtherRead | OtherWrite), //!< Mask to get the Other group permissions - GroupRW = (GroupRead | GroupWrite), - OwnerRW = (OwnerRead | OwnerWrite) - }; + /*! + * \brief The Type enum + */ + enum Type { File = 0x01, Directory = 0x02 }; - /*! - * \brief The Type enum - */ - enum Type - { - File = 0x01, - Directory = 0x02 - }; + WiiFile(); - WiiFile(); + /*! + * \brief WiiFile + * \param filename + */ + WiiFile(const std::string& filename); - /*! - * \brief WiiFile - * \param filename - */ - WiiFile(const std::string& filename); + /*! + * \brief WiiFile + * \param filename + * \param permissions + * \param data + * \param length + */ + WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length); + virtual ~WiiFile(); - /*! - * \brief WiiFile - * \param filename - * \param permissions - * \param data - * \param length - */ - WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length); - virtual ~WiiFile(); + /*! + * \brief setFilename + * \param filename + */ + void setFilename(const std::string& filename); - /*! - * \brief setFilename - * \param filename - */ - void setFilename(const std::string& filename); + /*! + * \brief filename + * \return + */ + std::string filename() const; - /*! - * \brief filename - * \return - */ - std::string filename() const; + /*! + * \brief setData + * \param data + */ + void setData(const atUint8* data); + /*! + * \brief data + * \return + */ + atUint8* data() const; - /*! - * \brief setData - * \param data - */ - void setData(const atUint8* data); - /*! - * \brief data - * \return - */ - atUint8* data() const; + /*! + * \brief setLength + * \param len + */ + void setLength(const int len); - /*! - * \brief setLength - * \param len - */ - void setLength(const int len); + /*! + * \brief length + * \return + */ + int length() const; - /*! - * \brief length - * \return - */ - int length() const; + /*! + * \brief setPermissions + * \param permissions + */ + void setPermissions(const atUint8 permissions); - /*! - * \brief setPermissions - * \param permissions - */ - void setPermissions(const atUint8 permissions); + /*! + * \brief permissions + * \return + */ + atUint8 permissions() const; - /*! - * \brief permissions - * \return - */ - atUint8 permissions() const; + /*! + * \brief setAttributes + * \param attr + */ + void setAttributes(const atUint8 attr); - /*! - * \brief setAttributes - * \param attr - */ - void setAttributes(const atUint8 attr); + /*! + * \brief attributes + * \return + */ + atUint8 attributes() const; - /*! - * \brief attributes - * \return - */ - atUint8 attributes() const; + /*! + * \brief setType + * \param type + */ + void setType(Type type); - /*! - * \brief setType - * \param type - */ - void setType(Type type); + /*! + * \brief type + * \return + */ + Type type() const; - /*! - * \brief type - * \return - */ - Type type() const; + /*! + * \brief isDirectory + * \return + */ + bool isDirectory() const; - /*! - * \brief isDirectory - * \return - */ - bool isDirectory() const; + /*! + * \brief isFile + * \return + */ + bool isFile() const; - /*! - * \brief isFile - * \return - */ - bool isFile() const; + /*! + * \brief addChild + * \param file + */ + void addChild(WiiFile* file); + /*! + * \brief children + * \return + */ + std::vector children(); + /*! + * \brief child + * \param name + * \return + */ + WiiFile* child(const std::string& name); + /*! + * \brief removeChild + * \param name + */ + void removeChild(const std::string& name); + /*! + * \brief removeChild + * \param file + */ + void removeChild(WiiFile* file); - /*! - * \brief addChild - * \param file - */ - void addChild(WiiFile* file); - /*! - * \brief children - * \return - */ - std::vector children(); - /*! - * \brief child - * \param name - * \return - */ - WiiFile* child(const std::string& name); - /*! - * \brief removeChild - * \param name - */ - void removeChild(const std::string& name); - /*! - * \brief removeChild - * \param file - */ - void removeChild(WiiFile* file); + /*! + * \brief parent + * \return + */ + WiiFile* parent(); - /*! - * \brief parent - * \return - */ - WiiFile* parent(); + /*! + * \brief setParent + * \param parent + */ + void setParent(WiiFile* parent); - /*! - * \brief setParent - * \param parent - */ - void setParent(WiiFile* parent); + /*! + * \brief fileCount + * \return + */ + atUint32 fileCount(); - /*! - * \brief fileCount - * \return - */ - atUint32 fileCount(); + /*! + * \brief allChildren + * \return + */ + std::vector allChildren(); - /*! - * \brief allChildren - * \return - */ - std::vector allChildren(); + /*! + * \brief fullpath + * \return + */ + std::string fullpath(); - /*! - * \brief fullpath - * \return - */ - std::string fullpath(); protected: private: - atUint8 m_permissions; - atUint8 m_attributes; - Type m_type; - std::string m_filename; - int m_fileLen; - atUint8* m_fileData; - WiiFile* m_parent; - std::vector m_children; + atUint8 m_permissions; + atUint8 m_attributes; + Type m_type; + std::string m_filename; + int m_fileLen; + atUint8* m_fileData; + WiiFile* m_parent; + std::vector m_children; }; -} // zelda +} // namespace athena diff --git a/include/athena/WiiImage.hpp b/include/athena/WiiImage.hpp index 37a69a3..2a8daa8 100644 --- a/include/athena/WiiImage.hpp +++ b/include/athena/WiiImage.hpp @@ -3,74 +3,71 @@ #include #include "athena/Types.hpp" -namespace athena -{ +namespace athena { /*! * \brief The WiiImage class */ -class WiiImage -{ +class WiiImage { public: - /*! - * \brief WiiImage - */ - WiiImage(); - /*! - * \brief WiiImage - * \param width - * \param height - * \param data - */ - WiiImage(atUint32 width, atUint32 height, std::unique_ptr&& data); + /*! + * \brief WiiImage + */ + WiiImage(); + /*! + * \brief WiiImage + * \param width + * \param height + * \param data + */ + WiiImage(atUint32 width, atUint32 height, std::unique_ptr&& data); - /*! - * \brief setWidth - * \param width - */ - void setWidth(const atUint32 width); + /*! + * \brief setWidth + * \param width + */ + void setWidth(const atUint32 width); - /*! - * \brief width - * \return - */ - atUint32 width() const; + /*! + * \brief width + * \return + */ + atUint32 width() const; - /*! - * \brief setHeight - * \param height - */ - void setHeight(const atUint32 height); + /*! + * \brief setHeight + * \param height + */ + void setHeight(const atUint32 height); - /*! - * \brief height - * \return - */ - atUint32 height() const; + /*! + * \brief height + * \return + */ + atUint32 height() const; - /*! - * \brief setData - * \param data - */ - void setData(const atUint8* data); + /*! + * \brief setData + * \param data + */ + void setData(const atUint8* data); - /*! - * \brief data - * \return - */ - atUint8* data(); + /*! + * \brief data + * \return + */ + atUint8* data(); - /*! - * \brief toRGBA - * \return - */ - atUint8* toRGBA(); + /*! + * \brief toRGBA + * \return + */ + atUint8* toRGBA(); private: - atUint32 m_width; - atUint32 m_height; - std::unique_ptr m_data; + atUint32 m_width; + atUint32 m_height; + std::unique_ptr m_data; }; -} // zelda - +} // namespace athena diff --git a/include/athena/WiiSave.hpp b/include/athena/WiiSave.hpp index 7ff3cea..821cff7 100644 --- a/include/athena/WiiSave.hpp +++ b/include/athena/WiiSave.hpp @@ -5,8 +5,7 @@ #include #include "athena/Global.hpp" -namespace athena -{ +namespace athena { class WiiFile; class WiiBanner; @@ -19,65 +18,61 @@ class BinaryWriter; * * Contains all relevant data for a Wii data.bin file. */ -class WiiSave -{ +class WiiSave { public: + /*! + * \brief FileIterator + */ + typedef std::unordered_map::const_iterator FileIterator; - /*! - * \brief FileIterator - */ - typedef std::unordered_map::const_iterator FileIterator; + /*! + * \brief WiiSave + */ + WiiSave(); + /*! + * \brief ~WiiSave + */ + virtual ~WiiSave(); - /*! - * \brief WiiSave - */ - WiiSave(); - /*! - * \brief ~WiiSave - */ - virtual ~WiiSave(); + /*! + * \brief addFile + * \param filename + * \param file + */ + void addFile(WiiFile* file); + void setRoot(WiiFile* root); + /*! + * \brief file + * \param filename + * \return + */ + WiiFile* file(const std::string& filename); - /*! - * \brief addFile - * \param filename - * \param file - */ - void addFile(WiiFile* file); - void setRoot(WiiFile* root); - /*! - * \brief file - * \param filename - * \return - */ - WiiFile* file(const std::string& filename); + atUint32 fileCount() const; + /*! + * \brief fileList + * \return + */ + WiiFile* root(); - atUint32 fileCount() const; - /*! - * \brief fileList - * \return - */ - WiiFile* root(); + /*! + * \brief setBanner + * \param banner + */ + void setBanner(WiiBanner* banner); - /*! - * \brief setBanner - * \param banner - */ - void setBanner(WiiBanner* banner); + /*! + * \brief banner + * \return + */ + WiiBanner* banner() const; - /*! - * \brief banner - * \return - */ - WiiBanner* banner() const; - - std::vector allFiles() const; + std::vector allFiles() const; protected: private: - - WiiFile* m_root; - WiiBanner* m_banner; - + WiiFile* m_root; + WiiBanner* m_banner; }; -} // zelda +} // namespace athena diff --git a/include/athena/WiiSaveReader.hpp b/include/athena/WiiSaveReader.hpp index 74f47c5..8fcad40 100644 --- a/include/athena/WiiSaveReader.hpp +++ b/include/athena/WiiSaveReader.hpp @@ -3,15 +3,13 @@ #include "athena/Global.hpp" #include "athena/MemoryReader.hpp" -namespace athena -{ +namespace athena { class WiiSave; class WiiBanner; class WiiFile; class WiiImage; -namespace io -{ +namespace io { /*! \class WiiSaveReader * \brief Wii data.bin reader class @@ -20,34 +18,34 @@ namespace io * all work is done using a memory buffer, and not read directly from the disk. * \sa BinaryReader */ -class WiiSaveReader : public MemoryCopyReader -{ +class WiiSaveReader : public MemoryCopyReader { public: - /*! \brief This constructor takes an existing buffer to read from. - * - * \param data The existing buffer - * \param length The length of the existing buffer - */ - WiiSaveReader(const atUint8*, atUint64); + /*! \brief This constructor takes an existing buffer to read from. + * + * \param data The existing buffer + * \param length The length of the existing buffer + */ + WiiSaveReader(const atUint8*, atUint64); - /*! \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - WiiSaveReader(const std::string&); + /*! \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + WiiSaveReader(const std::string&); + + /*! + * \brief readSave + * \return + */ + std::unique_ptr readSave(); - /*! - * \brief readSave - * \return - */ - std::unique_ptr readSave(); private: - WiiBanner* readBanner(); - WiiFile* readFile(); - WiiImage* readImage(atUint32 width, atUint32 height); - void readCerts(atUint32 totalSize); - WiiFile* buildTree(std::vector files); + WiiBanner* readBanner(); + WiiFile* readFile(); + WiiImage* readImage(atUint32 width, atUint32 height); + void readCerts(atUint32 totalSize); + WiiFile* buildTree(std::vector files); }; -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/include/athena/WiiSaveWriter.hpp b/include/athena/WiiSaveWriter.hpp index 6beb106..1746ee4 100644 --- a/include/athena/WiiSaveWriter.hpp +++ b/include/athena/WiiSaveWriter.hpp @@ -2,15 +2,13 @@ #include "athena/MemoryWriter.hpp" -namespace athena -{ +namespace athena { class WiiSave; class WiiBanner; class WiiFile; class WiiImage; -namespace io -{ +namespace io { /*! \class WiiSaveWriter * \brief Wii data.bin writer class @@ -19,34 +17,34 @@ namespace io * all work is done using a memory buffer, and not written directly to the disk. * \sa BinaryReader */ -class WiiSaveWriter : protected MemoryCopyWriter -{ +class WiiSaveWriter : protected MemoryCopyWriter { public: - /*! \brief This constructor creates an instance from a file on disk. - * - * \param filename The file to create the stream from - */ - WiiSaveWriter(const std::string&); + /*! \brief This constructor creates an instance from a file on disk. + * + * \param filename The file to create the stream from + */ + WiiSaveWriter(const std::string&); - /*! - * \brief writeSave - * \param save - * \param macAddress - * \param ngId - * \param ngPriv - * \param ngSig - * \param ngKeyId - * \param filepath - * \return - */ - bool writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId, const std::string& filepath = ""); + /*! + * \brief writeSave + * \param save + * \param macAddress + * \param ngId + * \param ngPriv + * \param ngSig + * \param ngKeyId + * \param filepath + * \return + */ + bool writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId, + const std::string& filepath = ""); private: - void writeBanner(WiiBanner* banner); - atUint32 writeFile(WiiFile* file); - void writeImage(WiiImage* image); - void writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId); + void writeBanner(WiiBanner* banner); + atUint32 writeFile(WiiFile* file); + void writeImage(WiiImage* image); + void writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId); }; -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/include/athena/YAMLCommon.hpp b/include/athena/YAMLCommon.hpp index 451d64c..f5d03eb 100644 --- a/include/athena/YAMLCommon.hpp +++ b/include/athena/YAMLCommon.hpp @@ -12,157 +12,147 @@ #include #include "Global.hpp" -namespace athena::io -{ +namespace athena::io { class IStreamReader; class IStreamWriter; -enum class YAMLNodeStyle -{ - Any, - Flow, - Block +enum class YAMLNodeStyle { Any, Flow, Block }; + +struct YAMLNode { + yaml_node_type_t m_type; + std::string m_scalarString; + std::vector> m_seqChildren; + std::vector>> m_mapChildren; + YAMLNodeStyle m_style = YAMLNodeStyle::Any; + + YAMLNode(yaml_node_type_t type) : m_type(type) {} + + inline const YAMLNode* findMapChild(std::string_view key) const { + for (const auto& item : m_mapChildren) + if (!item.first.compare(key)) + return item.second.get(); + return nullptr; + } + + inline void assignMapChild(std::string_view key, std::unique_ptr&& node) { + for (auto& item : m_mapChildren) + if (!item.first.compare(key)) { + item.second = std::move(node); + return; + } + m_mapChildren.emplace_back(key, std::move(node)); + } }; -struct YAMLNode -{ - yaml_node_type_t m_type; - std::string m_scalarString; - std::vector> m_seqChildren; - std::vector>> m_mapChildren; - YAMLNodeStyle m_style = YAMLNodeStyle::Any; - - YAMLNode(yaml_node_type_t type) : m_type(type) {} - - inline const YAMLNode* findMapChild(std::string_view key) const - { - for (const auto& item : m_mapChildren) - if (!item.first.compare(key)) - return item.second.get(); - return nullptr; - } - - inline void assignMapChild(std::string_view key, std::unique_ptr && node) - { - for (auto& item : m_mapChildren) - if (!item.first.compare(key)) - { - item.second = std::move(node); - return; - } - m_mapChildren.emplace_back(key, std::move(node)); - } -}; - -template +template RETURNTYPE NodeToVal(const YAMLNode* node); -template<> +template <> bool NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(bool val); +std::unique_ptr ValToNode(bool val); -template<> +template <> atInt8 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atInt8 val); +std::unique_ptr ValToNode(atInt8 val); -template<> +template <> atUint8 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atUint8 val); +std::unique_ptr ValToNode(atUint8 val); -template<> +template <> atInt16 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atInt16 val); +std::unique_ptr ValToNode(atInt16 val); -template<> +template <> atUint16 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atUint16 val); +std::unique_ptr ValToNode(atUint16 val); -template<> +template <> atInt32 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atInt32 val); +std::unique_ptr ValToNode(atInt32 val); -template<> +template <> atUint32 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atUint32 val); +std::unique_ptr ValToNode(atUint32 val); -template<> +template <> atInt64 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atInt64 val); +std::unique_ptr ValToNode(atInt64 val); -template<> +template <> atUint64 NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(atUint64 val); +std::unique_ptr ValToNode(atUint64 val); -template<> +template <> float NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(float val); +std::unique_ptr ValToNode(float val); -template<> +template <> double NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(double val); +std::unique_ptr ValToNode(double val); -template +template RETURNTYPE NodeToVec(const YAMLNode* node); -template<> +template <> atVec2f NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const atVec2f& val); +std::unique_ptr ValToNode(const atVec2f& val); -template<> +template <> atVec3f NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const atVec3f& val); +std::unique_ptr ValToNode(const atVec3f& val); -template<> +template <> atVec4f NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const atVec4f& val); +std::unique_ptr ValToNode(const atVec4f& val); -template<> +template <> atVec2d NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const atVec2d& val); +std::unique_ptr ValToNode(const atVec2d& val); -template<> +template <> atVec3d NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const atVec3d& val); +std::unique_ptr ValToNode(const atVec3d& val); -template<> +template <> atVec4d NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const atVec4d& val); +std::unique_ptr ValToNode(const atVec4d& val); -template<> +template <> std::unique_ptr NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(const std::unique_ptr& val, size_t byteCount); +std::unique_ptr ValToNode(const std::unique_ptr& val, size_t byteCount); -template<> +template <> std::string NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(std::string_view val); +std::unique_ptr ValToNode(std::string_view val); -template<> +template <> std::wstring NodeToVal(const YAMLNode* node); -std::unique_ptr ValToNode(std::wstring_view val); +std::unique_ptr ValToNode(std::wstring_view val); -std::unique_ptr ValToNode(std::u16string_view val); +std::unique_ptr ValToNode(std::u16string_view val); -std::unique_ptr ValToNode(std::u32string_view val); +std::unique_ptr ValToNode(std::u32string_view val); std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len); @@ -172,28 +162,22 @@ void HandleYAMLParserError(yaml_parser_t* parser); void HandleYAMLEmitterError(yaml_emitter_t* emitter); -struct YAMLStdStringViewReaderState -{ - std::string_view::const_iterator begin; - std::string_view::const_iterator end; +struct YAMLStdStringViewReaderState { + std::string_view::const_iterator begin; + std::string_view::const_iterator end; - YAMLStdStringViewReaderState(std::string_view str) - { - begin = str.begin(); - end = str.end(); - } + YAMLStdStringViewReaderState(std::string_view str) { + begin = str.begin(); + end = str.end(); + } }; -int YAMLStdStringReader(YAMLStdStringViewReaderState* str, - unsigned char* buffer, size_t size, size_t* size_read); +int YAMLStdStringReader(YAMLStdStringViewReaderState* str, unsigned char* buffer, size_t size, size_t* size_read); int YAMLStdStringWriter(std::string* str, unsigned char* buffer, size_t size); -int YAMLAthenaReader(athena::io::IStreamReader* reader, - unsigned char* buffer, size_t size, size_t* size_read); +int YAMLAthenaReader(athena::io::IStreamReader* reader, unsigned char* buffer, size_t size, size_t* size_read); -int YAMLAthenaWriter(athena::io::IStreamWriter* writer, - unsigned char* buffer, size_t size); - -} +int YAMLAthenaWriter(athena::io::IStreamWriter* writer, unsigned char* buffer, size_t size); +} // namespace athena::io diff --git a/include/athena/YAMLDocReader.hpp b/include/athena/YAMLDocReader.hpp index bc8df06..8fa4c00 100644 --- a/include/athena/YAMLDocReader.hpp +++ b/include/athena/YAMLDocReader.hpp @@ -2,168 +2,160 @@ #include "YAMLCommon.hpp" -namespace athena::io -{ +namespace athena::io { -class YAMLDocReader -{ - std::unique_ptr m_rootNode; - std::vector m_subStack; - std::vector m_seqTrackerStack; - yaml_parser_t m_parser; - std::unique_ptr ParseEvents(athena::io::IStreamReader* reader); - void _leaveSubRecord(); - void _leaveSubVector(); +class YAMLDocReader { + std::unique_ptr m_rootNode; + std::vector m_subStack; + std::vector m_seqTrackerStack; + yaml_parser_t m_parser; + std::unique_ptr ParseEvents(athena::io::IStreamReader* reader); + void _leaveSubRecord(); + void _leaveSubVector(); public: - YAMLDocReader(); - ~YAMLDocReader(); + YAMLDocReader(); + ~YAMLDocReader(); - void reset(); + void reset(); - inline yaml_parser_t* getParser() { return &m_parser; } + inline yaml_parser_t* getParser() { return &m_parser; } - bool parse(athena::io::IStreamReader* reader); + bool parse(athena::io::IStreamReader* reader); - bool ClassTypeOperation(std::function func); - bool ValidateClassType(const char* expectedType); + bool ClassTypeOperation(std::function func); + bool ValidateClassType(const char* expectedType); - inline const YAMLNode* getRootNode() const { return m_rootNode.get(); } - inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); } - std::unique_ptr releaseRootNode() { return std::move(m_rootNode); } + inline const YAMLNode* getRootNode() const { return m_rootNode.get(); } + inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); } + std::unique_ptr releaseRootNode() { return std::move(m_rootNode); } - class RecordRAII - { - friend class YAMLDocReader; - YAMLDocReader* m_r = nullptr; - RecordRAII(YAMLDocReader* r) : m_r(r) {} - RecordRAII() = default; - public: - operator bool() const { return m_r != nullptr; } - void leave() { if (m_r) {m_r->_leaveSubRecord(); m_r = nullptr;} } - ~RecordRAII() { if (m_r) m_r->_leaveSubRecord(); } - }; - friend class RecordRAII; + class RecordRAII { + friend class YAMLDocReader; + YAMLDocReader* m_r = nullptr; + RecordRAII(YAMLDocReader* r) : m_r(r) {} + RecordRAII() = default; - RecordRAII enterSubRecord(const char* name); - - template - void enumerate(const char* name, T& record, - typename std::enable_if_t<__IsDNARecord_v>* = 0) - { - if (auto rec = enterSubRecord(name)) - record.read(*this); + public: + operator bool() const { return m_r != nullptr; } + void leave() { + if (m_r) { + m_r->_leaveSubRecord(); + m_r = nullptr; + } } - - class VectorRAII - { - friend class YAMLDocReader; - YAMLDocReader* m_r = nullptr; - VectorRAII(YAMLDocReader* r) : m_r(r) {} - VectorRAII() = default; - public: - operator bool() const { return m_r != nullptr; } - ~VectorRAII() { if (m_r) m_r->_leaveSubVector(); } - }; - friend class VectorRAII; - - VectorRAII enterSubVector(const char* name, size_t& countOut); - - template - size_t enumerate(const char* name, std::vector& vector, - typename std::enable_if_t::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value>* = 0) - { - size_t countOut; - if (auto v = enterSubVector(name, countOut)) - { - vector.clear(); - vector.reserve(countOut); - for (size_t i=0 ; i_leaveSubRecord(); } + }; + friend class RecordRAII; - template - size_t enumerate(const char* name, std::vector& vector, - typename std::enable_if_t::value || - std::is_same::value || - std::is_same::value || - std::is_same::value>* = 0) - { - size_t countOut; - if (auto v = enterSubVector(name, countOut)) - { - vector.clear(); - vector.reserve(countOut); - for (size_t i=0 ; i(name)); - } - return countOut; + RecordRAII enterSubRecord(const char* name); + + template + void enumerate(const char* name, T& record, typename std::enable_if_t<__IsDNARecord_v>* = 0) { + if (auto rec = enterSubRecord(name)) + record.read(*this); + } + + class VectorRAII { + friend class YAMLDocReader; + YAMLDocReader* m_r = nullptr; + VectorRAII(YAMLDocReader* r) : m_r(r) {} + VectorRAII() = default; + + public: + operator bool() const { return m_r != nullptr; } + ~VectorRAII() { + if (m_r) + m_r->_leaveSubVector(); } + }; + friend class VectorRAII; - template - size_t enumerate(const char* name, std::vector& vector, - std::function readf) - { - size_t countOut; - if (auto v = enterSubVector(name, countOut)) - { - vector.clear(); - vector.reserve(countOut); - for (size_t i=0 ; i + size_t + enumerate(const char* name, std::vector& vector, + typename std::enable_if_t::value && !std::is_same::value && + !std::is_same::value && !std::is_same::value>* = 0) { + size_t countOut; + if (auto v = enterSubVector(name, countOut)) { + vector.clear(); + vector.reserve(countOut); + for (size_t i = 0; i < countOut; ++i) { + vector.emplace_back(); + if (auto rec = enterSubRecord(nullptr)) + vector.back().read(*this); + } } + return countOut; + } - bool hasVal(const char* name) const - { - if (m_subStack.size()) - { - const YAMLNode* mnode = m_subStack.back(); - if (mnode->m_type == YAML_MAPPING_NODE && name) - for (const auto& item : mnode->m_mapChildren) - if (!item.first.compare(name)) - return true; - } - return false; + template + size_t enumerate(const char* name, std::vector& vector, + typename std::enable_if_t::value || std::is_same::value || + std::is_same::value || std::is_same::value>* = 0) { + size_t countOut; + if (auto v = enterSubVector(name, countOut)) { + vector.clear(); + vector.reserve(countOut); + for (size_t i = 0; i < countOut; ++i) + vector.push_back(readVal(name)); } + return countOut; + } - template - RETURNTYPE readVal(const char* name); - bool readBool(const char* name); - atInt8 readByte(const char* name); - atUint8 readUByte(const char* name); - atInt16 readInt16(const char* name); - atUint16 readUint16(const char* name); - atInt32 readInt32(const char* name); - atUint32 readUint32(const char* name); - atInt64 readInt64(const char* name); - atUint64 readUint64(const char* name); - float readFloat(const char* name); - double readDouble(const char* name); - atVec2f readVec2f(const char* name); - atVec3f readVec3f(const char* name); - atVec4f readVec4f(const char* name); - atVec2d readVec2d(const char* name); - atVec3d readVec3d(const char* name); - atVec4d readVec4d(const char* name); - std::unique_ptr readUBytes(const char* name); - std::string readString(const char* name); - std::wstring readWString(const char* name); + template + size_t enumerate(const char* name, std::vector& vector, std::function readf) { + size_t countOut; + if (auto v = enterSubVector(name, countOut)) { + vector.clear(); + vector.reserve(countOut); + for (size_t i = 0; i < countOut; ++i) { + vector.emplace_back(); + if (auto rec = enterSubRecord(nullptr)) + readf(*this, vector.back()); + } + } + return countOut; + } + + bool hasVal(const char* name) const { + if (m_subStack.size()) { + const YAMLNode* mnode = m_subStack.back(); + if (mnode->m_type == YAML_MAPPING_NODE && name) + for (const auto& item : mnode->m_mapChildren) + if (!item.first.compare(name)) + return true; + } + return false; + } + + template + RETURNTYPE readVal(const char* name); + bool readBool(const char* name); + atInt8 readByte(const char* name); + atUint8 readUByte(const char* name); + atInt16 readInt16(const char* name); + atUint16 readUint16(const char* name); + atInt32 readInt32(const char* name); + atUint32 readUint32(const char* name); + atInt64 readInt64(const char* name); + atUint64 readUint64(const char* name); + float readFloat(const char* name); + double readDouble(const char* name); + atVec2f readVec2f(const char* name); + atVec3f readVec3f(const char* name); + atVec4f readVec4f(const char* name); + atVec2d readVec2d(const char* name); + atVec3d readVec3d(const char* name); + atVec4d readVec4d(const char* name); + std::unique_ptr readUBytes(const char* name); + std::string readString(const char* name); + std::wstring readWString(const char* name); }; -} - +} // namespace athena::io diff --git a/include/athena/YAMLDocWriter.hpp b/include/athena/YAMLDocWriter.hpp index 0824006..ae9cbc4 100644 --- a/include/athena/YAMLDocWriter.hpp +++ b/include/athena/YAMLDocWriter.hpp @@ -2,133 +2,125 @@ #include "YAMLCommon.hpp" -namespace athena::io -{ +namespace athena::io { + +class YAMLDocWriter { + std::unique_ptr m_rootNode; + std::vector m_subStack; + yaml_emitter_t m_emitter; + static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node); + void _leaveSubRecord(); + void _leaveSubVector(); -class YAMLDocWriter -{ - std::unique_ptr m_rootNode; - std::vector m_subStack; - yaml_emitter_t m_emitter; - static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node); - void _leaveSubRecord(); - void _leaveSubVector(); public: - YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader = nullptr); - ~YAMLDocWriter(); + YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader = nullptr); + ~YAMLDocWriter(); - yaml_emitter_t* getEmitter() { return &m_emitter; } + yaml_emitter_t* getEmitter() { return &m_emitter; } - bool finish(athena::io::IStreamWriter* fout); + bool finish(athena::io::IStreamWriter* fout); - inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); } + inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); } - class RecordRAII - { - friend class YAMLDocWriter; - YAMLDocWriter* m_w = nullptr; - RecordRAII(YAMLDocWriter* w) : m_w(w) {} - RecordRAII() = default; - public: - operator bool() const { return m_w != nullptr; } - ~RecordRAII() { if (m_w) m_w->_leaveSubRecord(); } - }; - friend class RecordRAII; + class RecordRAII { + friend class YAMLDocWriter; + YAMLDocWriter* m_w = nullptr; + RecordRAII(YAMLDocWriter* w) : m_w(w) {} + RecordRAII() = default; - RecordRAII enterSubRecord(const char* name); - - template - void enumerate(const char* name, T& record, - typename std::enable_if_t<__IsDNARecord_v>* = 0) - { - if (auto rec = enterSubRecord(name)) - record.write(*this); + public: + operator bool() const { return m_w != nullptr; } + ~RecordRAII() { + if (m_w) + m_w->_leaveSubRecord(); } + }; + friend class RecordRAII; - class VectorRAII - { - friend class YAMLDocWriter; - YAMLDocWriter* m_w = nullptr; - VectorRAII(YAMLDocWriter* w) : m_w(w) {} - VectorRAII() = default; - public: - operator bool() const { return m_w != nullptr; } - ~VectorRAII() { if (m_w) m_w->_leaveSubVector(); } - }; - friend class VectorRAII; + RecordRAII enterSubRecord(const char* name); - VectorRAII enterSubVector(const char* name); + template + void enumerate(const char* name, T& record, typename std::enable_if_t<__IsDNARecord_v>* = 0) { + if (auto rec = enterSubRecord(name)) + record.write(*this); + } - template - void enumerate(const char* name, const std::vector& vector, - typename std::enable_if_t::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value>* = 0) - { - if (auto v = enterSubVector(name)) - for (const T& item : vector) - if (auto rec = enterSubRecord(nullptr)) - item.write(*this); + class VectorRAII { + friend class YAMLDocWriter; + YAMLDocWriter* m_w = nullptr; + VectorRAII(YAMLDocWriter* w) : m_w(w) {} + VectorRAII() = default; + + public: + operator bool() const { return m_w != nullptr; } + ~VectorRAII() { + if (m_w) + m_w->_leaveSubVector(); } + }; + friend class VectorRAII; - template - void enumerate(const char* name, const std::vector& vector, - typename std::enable_if_t::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value>* = 0) - { - if (auto v = enterSubVector(name)) - for (T item : vector) - writeVal(nullptr, item); - } + VectorRAII enterSubVector(const char* name); - template - void enumerate(const char* name, const std::vector& vector, - std::function writef) - { - if (auto v = enterSubVector(name)) - for (const T& item : vector) - if (auto rec = enterSubRecord(nullptr)) - writef(*this, item); - } + template + void enumerate(const char* name, const std::vector& vector, + typename std::enable_if_t::value && !std::is_same::value && + !std::is_same::value && !std::is_same::value && + !std::is_same::value && !std::is_same::value && + !std::is_same::value>* = 0) { + if (auto v = enterSubVector(name)) + for (const T& item : vector) + if (auto rec = enterSubRecord(nullptr)) + item.write(*this); + } - template - void writeVal(const char* name, const INTYPE& val); - template - void writeVal(const char* name, const INTYPE& val, size_t byteCount); - void writeBool(const char* name, const bool& val); - void writeByte(const char* name, const atInt8& val); - void writeUByte(const char* name, const atUint8& val); - void writeInt16(const char* name, const atInt16& val); - void writeUint16(const char* name, const atUint16& val); - void writeInt32(const char* name, const atInt32& val); - void writeUint32(const char* name, const atUint32& val); - void writeInt64(const char* name, const atInt64& val); - void writeUint64(const char* name, const atUint64& val); - void writeFloat(const char* name, const float& val); - void writeDouble(const char* name, const double& val); - void writeVec2f(const char* name, const atVec2f& val); - void writeVec3f(const char* name, const atVec3f& val); - void writeVec4f(const char* name, const atVec4f& val); - void writeVec2d(const char* name, const atVec2d& val); - void writeVec3d(const char* name, const atVec3d& val); - void writeVec4d(const char* name, const atVec4d& val); - void writeUBytes(const char* name, const std::unique_ptr& val, size_t byteCount); - void writeString(const char* name, std::string_view val); - void writeWString(const char* name, std::wstring_view val); - void writeU16String(const char* name, std::u16string_view val); - void writeU32String(const char* name, std::u32string_view val); + template + void enumerate(const char* name, const std::vector& vector, + typename std::enable_if_t::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value>* = 0) { + if (auto v = enterSubVector(name)) + for (T item : vector) + writeVal(nullptr, item); + } - void setStyle(YAMLNodeStyle s); + template + void enumerate(const char* name, const std::vector& vector, std::function writef) { + if (auto v = enterSubVector(name)) + for (const T& item : vector) + if (auto rec = enterSubRecord(nullptr)) + writef(*this, item); + } + + template + void writeVal(const char* name, const INTYPE& val); + template + void writeVal(const char* name, const INTYPE& val, size_t byteCount); + void writeBool(const char* name, const bool& val); + void writeByte(const char* name, const atInt8& val); + void writeUByte(const char* name, const atUint8& val); + void writeInt16(const char* name, const atInt16& val); + void writeUint16(const char* name, const atUint16& val); + void writeInt32(const char* name, const atInt32& val); + void writeUint32(const char* name, const atUint32& val); + void writeInt64(const char* name, const atInt64& val); + void writeUint64(const char* name, const atUint64& val); + void writeFloat(const char* name, const float& val); + void writeDouble(const char* name, const double& val); + void writeVec2f(const char* name, const atVec2f& val); + void writeVec3f(const char* name, const atVec3f& val); + void writeVec4f(const char* name, const atVec4f& val); + void writeVec2d(const char* name, const atVec2d& val); + void writeVec3d(const char* name, const atVec3d& val); + void writeVec4d(const char* name, const atVec4d& val); + void writeUBytes(const char* name, const std::unique_ptr& val, size_t byteCount); + void writeString(const char* name, std::string_view val); + void writeWString(const char* name, std::wstring_view val); + void writeU16String(const char* name, std::u16string_view val); + void writeU32String(const char* name, std::u32string_view val); + + void setStyle(YAMLNodeStyle s); }; -} - +} // namespace athena::io diff --git a/include/athena/ZQuestFile.hpp b/include/athena/ZQuestFile.hpp index 07944e8..35f2988 100644 --- a/include/athena/ZQuestFile.hpp +++ b/include/athena/ZQuestFile.hpp @@ -2,151 +2,148 @@ #ifndef ZQUEST_HPP #define ZQUEST_HPP - #include "athena/Global.hpp" #include #include #include -#define ZQUEST_VERSION_CHECK(major, minor, revision) \ - (major | (minor << 8) | (revision << 16)) +#define ZQUEST_VERSION_CHECK(major, minor, revision) (major | (minor << 8) | (revision << 16)) -namespace athena -{ +namespace athena { /*! * \brief ZQuestFile is an export format for save data. */ -class ZQuestFile -{ +class ZQuestFile { public: - /*! - * \brief The current major version of the ZQuest format - */ - static const atUint32 Major; - /*! - * \brief The current minor version of the ZQuest format - */ - static const atUint32 Minor; - /*! - * \brief The current revision of the ZQuest format - */ - static const atUint32 Revision; - /*! - * \brief The current version of the ZQuest format - */ - static const atUint32 Version; + /*! + * \brief The current major version of the ZQuest format + */ + static const atUint32 Major; + /*! + * \brief The current minor version of the ZQuest format + */ + static const atUint32 Minor; + /*! + * \brief The current revision of the ZQuest format + */ + static const atUint32 Revision; + /*! + * \brief The current version of the ZQuest format + */ + static const atUint32 Version; - /*! - * \brief The magic number used to identify the file e.g. "ZQS1" - */ - static const atUint32 Magic; + /*! + * \brief The magic number used to identify the file e.g. "ZQS1" + */ + static const atUint32 Magic; - /*! - * \enum Game - * \brief The list of games currently supported by ZQuest - */ - enum Game - { - NoGame, //!< None or Unsupported - LoZ, //!< Legend of Zelda - AoL, //!< Adventure of Link - ALttP, //!< A Link to the Past - LA, //!< Links Awakening - OoT, //!< Ocarin of Time - OoT3D, //!< Ocarina of Time 3D - MM, //!< Majora's Mask - OoS, //!< Oracle of Season - OoA, //!< Oracle of Ages - FS, //!< Four Swords - WW, //!< Wind Waker - FSA, //!< Four Swords Adventures - MC, //!< Minish Cap - TP, //!< Twilight Princess - PH, //!< Phantom Hourglass - ST, //!< Spirit Tracks - SS, //!< Skyward Sword - ALBW, //!< A Link Between Worlds - // Add more games here + /*! + * \enum Game + * \brief The list of games currently supported by ZQuest + */ + enum Game { + NoGame, //!< None or Unsupported + LoZ, //!< Legend of Zelda + AoL, //!< Adventure of Link + ALttP, //!< A Link to the Past + LA, //!< Links Awakening + OoT, //!< Ocarin of Time + OoT3D, //!< Ocarina of Time 3D + MM, //!< Majora's Mask + OoS, //!< Oracle of Season + OoA, //!< Oracle of Ages + FS, //!< Four Swords + WW, //!< Wind Waker + FSA, //!< Four Swords Adventures + MC, //!< Minish Cap + TP, //!< Twilight Princess + PH, //!< Phantom Hourglass + ST, //!< Spirit Tracks + SS, //!< Skyward Sword + ALBW, //!< A Link Between Worlds + // Add more games here - // This must always be last - GameCount //!< Total number of supported games - }; + // This must always be last + GameCount //!< Total number of supported games + }; - /*! - * \brief ZQuest - */ - ZQuestFile(); + /*! + * \brief ZQuest + */ + ZQuestFile(); - /*! - * \brief ZQuest - * \param game - * \param endian - * \param data - * \param length - */ - ZQuestFile(Game game, Endian endian, std::unique_ptr&& data, atUint32 length, const std::string& gameString = std::string()); + /*! + * \brief ZQuest + * \param game + * \param endian + * \param data + * \param length + */ + ZQuestFile(Game game, Endian endian, std::unique_ptr&& data, atUint32 length, + const std::string& gameString = std::string()); - /*! - * \brief setGame - * \param game - */ - void setGame(Game game); + /*! + * \brief setGame + * \param game + */ + void setGame(Game game); - /*! - * \brief game - * \return - */ - Game game() const; + /*! + * \brief game + * \return + */ + Game game() const; - /*! - * \brief setEndian - * \param endian - */ - void setEndian(Endian endian); + /*! + * \brief setEndian + * \param endian + */ + void setEndian(Endian endian); - /*! - * \brief endian - * \return - */ - Endian endian() const; + /*! + * \brief endian + * \return + */ + Endian endian() const; - /*! - * \brief setData - * \param data The data to assign - * \param length The length of the data - */ - void setData(std::unique_ptr&& data, atUint32 length); + /*! + * \brief setData + * \param data The data to assign + * \param length The length of the data + */ + void setData(std::unique_ptr&& data, atUint32 length); - /*! - * \brief data - * \return - */ - atUint8* data() const; + /*! + * \brief data + * \return + */ + atUint8* data() const; - /*! - * \brief length - * \return - */ - atUint32 length() const; + /*! + * \brief length + * \return + */ + atUint32 length() const; - void setGameString(const std::string& gameString); - /*! - * \brief gameString - * \return - */ - std::string gameString() const; + void setGameString(const std::string& gameString); + /*! + * \brief gameString + * \return + */ + std::string gameString() const; + + static const std::vector gameStringList(); - static const std::vector gameStringList(); protected: - Game m_game; - std::string m_gameString; - Endian m_endian; - std::unique_ptr m_data; - atUint32 m_length; + Game m_game; + std::string m_gameString; + Endian m_endian; + std::unique_ptr m_data; + atUint32 m_length; - // Game strings support + // Game strings support }; -} // zelda +} // namespace athena #endif // ZQUEST_HPP #endif // ATHENA_NO_ZQUEST diff --git a/include/athena/ZQuestFileReader.hpp b/include/athena/ZQuestFileReader.hpp index 24431d8..447ebda 100644 --- a/include/athena/ZQuestFileReader.hpp +++ b/include/athena/ZQuestFileReader.hpp @@ -4,42 +4,39 @@ #include "athena/MemoryReader.hpp" -namespace athena -{ +namespace athena { class ZQuestFile; -namespace io -{ +namespace io { /*! * \brief The ZQuestFileReader class */ -class ZQuestFileReader : protected MemoryCopyReader -{ +class ZQuestFileReader : protected MemoryCopyReader { public: - /*! - * \brief ZQuestFileReader - * \param data - * \param length - */ - ZQuestFileReader(atUint8* data, atUint64 length); + /*! + * \brief ZQuestFileReader + * \param data + * \param length + */ + ZQuestFileReader(atUint8* data, atUint64 length); - /*! - * \brief ZQuestFileReader - * \param filename - */ - ZQuestFileReader(const std::string& filename); + /*! + * \brief ZQuestFileReader + * \param filename + */ + ZQuestFileReader(const std::string& filename); - /*! - * \brief read - * \return - */ - ZQuestFile* read(); + /*! + * \brief read + * \return + */ + ZQuestFile* read(); }; -} // io -} // zelda +} // namespace io +} // namespace athena #endif // __ZQUESTFILEREADER_HPP__ diff --git a/include/athena/ZQuestFileWriter.hpp b/include/athena/ZQuestFileWriter.hpp index 7c09fb1..2714bca 100644 --- a/include/athena/ZQuestFileWriter.hpp +++ b/include/athena/ZQuestFileWriter.hpp @@ -4,42 +4,39 @@ #include "athena/MemoryWriter.hpp" -namespace athena -{ +namespace athena { class ZQuestFile; -namespace io -{ +namespace io { /*! * \brief The ZQuestFileWriter class */ -class ZQuestFileWriter : protected MemoryCopyWriter -{ +class ZQuestFileWriter : protected MemoryCopyWriter { public: - /*! - * \brief ZQuestFileWriter - * \param data - * \param length - */ - ZQuestFileWriter(atUint8* data, atUint64 length); + /*! + * \brief ZQuestFileWriter + * \param data + * \param length + */ + ZQuestFileWriter(atUint8* data, atUint64 length); - /*! - * \brief ZQuestFileWriter - * \param filename - */ - ZQuestFileWriter(const std::string& filename); + /*! + * \brief ZQuestFileWriter + * \param filename + */ + ZQuestFileWriter(const std::string& filename); - /*! - * \brief write - * \param quest - * \param compress - */ - void write(ZQuestFile* quest, bool compress = true); + /*! + * \brief write + * \param quest + * \param compress + */ + void write(ZQuestFile* quest, bool compress = true); }; -} // io -} // zelda +} // namespace io +} // namespace athena #endif // __ZQUESTFILEWRITER_HPP__ #endif // ATHENA_NO_ZQUEST diff --git a/include/athena/simd/parallelism_v2_simd.hpp b/include/athena/simd/parallelism_v2_simd.hpp index 14606ee..2b1f152 100644 --- a/include/athena/simd/parallelism_v2_simd.hpp +++ b/include/athena/simd/parallelism_v2_simd.hpp @@ -688,21 +688,16 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { public: _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }; - void __set(size_t __index, _Tp __val) noexcept { - (&__storage_)[__index] = __val; - } + void __set(size_t __index, _Tp __val) noexcept { (&__storage_)[__index] = __val; } }; #ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION constexpr size_t __floor_pow_of_2(size_t __val) { - return ((__val - 1) & __val) == 0 ? __val - : __floor_pow_of_2((__val - 1) & __val); + return ((__val - 1) & __val) == 0 ? __val : __floor_pow_of_2((__val - 1) & __val); } -constexpr size_t __ceil_pow_of_2(size_t __val) { - return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; -} +constexpr size_t __ceil_pow_of_2(size_t __val) { return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; } template struct __vec_ext_traits { @@ -712,45 +707,44 @@ struct __vec_ext_traits { }; #if defined(_LIBCPP_COMPILER_CLANG) -#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ - template <> \ - struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ - using type = \ - _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ +#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ + template <> \ + struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ + using type = _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ } -#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ +#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32); _LIBCPP_SPECIALIZE_VEC_EXT_32(char); @@ -777,8 +771,7 @@ _LIBCPP_SPECIALIZE_VEC_EXT_32(long double); template class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { - using _StorageType = - typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; + using _StorageType = typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; _StorageType __storage_; @@ -790,9 +783,7 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { public: _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; - void __set(size_t __index, _Tp __val) noexcept { - __storage_[__index] = __val; - } + void __set(size_t __index, _Tp __val) noexcept { __storage_[__index] = __val; } }; #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION @@ -810,8 +801,7 @@ class __simd_reference { __simd_storage<_Tp, _Abi>* __ptr_; size_t __index_; - __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) - : __ptr_(__ptr), __index_(__index) {} + __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) : __ptr_(__ptr), __index_(__index) {} __simd_reference(const __simd_reference&) = default; @@ -826,9 +816,7 @@ public: return *this; } - __simd_reference operator++() && { - return std::move(*this) = __ptr_->__get(__index_) + 1; - } + __simd_reference operator++() && { return std::move(*this) = __ptr_->__get(__index_) + 1; } _Vp operator++(int) && { auto __val = __ptr_->__get(__index_); @@ -836,9 +824,7 @@ public: return __val; } - __simd_reference operator--() && { - return std::move(*this) = __ptr_->__get(__index_) - 1; - } + __simd_reference operator--() && { return std::move(*this) = __ptr_->__get(__index_) - 1; } _Vp operator--(int) && { auto __val = __ptr_->__get(__index_); @@ -846,69 +832,37 @@ public: return __val; } - __simd_reference operator+=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) + __value; - } + __simd_reference operator+=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) + __value; } - __simd_reference operator-=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) - __value; - } + __simd_reference operator-=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) - __value; } - __simd_reference operator*=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) * __value; - } + __simd_reference operator*=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) * __value; } - __simd_reference operator/=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) / __value; - } + __simd_reference operator/=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) / __value; } - __simd_reference operator%=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) % __value; - } + __simd_reference operator%=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) % __value; } - __simd_reference operator>>=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) >> __value; - } + __simd_reference operator>>=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) >> __value; } - __simd_reference operator<<=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) << __value; - } + __simd_reference operator<<=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) << __value; } - __simd_reference operator&=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) & __value; - } + __simd_reference operator&=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) & __value; } - __simd_reference operator|=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) | __value; - } + __simd_reference operator|=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) | __value; } - __simd_reference operator^=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) ^ __value; - } + __simd_reference operator^=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) ^ __value; } - bool operator<(_Vp __value) const { - return __ptr_->__get(__index_) < __value; - } + bool operator<(_Vp __value) const { return __ptr_->__get(__index_) < __value; } - bool operator<=(_Vp __value) const { - return __ptr_->__get(__index_) <= __value; - } + bool operator<=(_Vp __value) const { return __ptr_->__get(__index_) <= __value; } - bool operator>(_Vp __value) const { - return __ptr_->__get(__index_) > __value; - } + bool operator>(_Vp __value) const { return __ptr_->__get(__index_) > __value; } - bool operator>=(_Vp __value) const { - return __ptr_->__get(__index_) >= __value; - } + bool operator>=(_Vp __value) const { return __ptr_->__get(__index_) >= __value; } - bool operator==(_Vp __value) const { - return __ptr_->__get(__index_) == __value; - } + bool operator==(_Vp __value) const { return __ptr_->__get(__index_) == __value; } - bool operator!=(_Vp __value) const { - return __ptr_->__get(__index_) != __value; - } + bool operator!=(_Vp __value) const { return __ptr_->__get(__index_) != __value; } }; template @@ -922,8 +876,7 @@ class __simd_mask_reference { __simd_mask_storage<_Tp, _Abi>* __ptr_; size_t __index_; - __simd_mask_reference(__simd_mask_storage<_Tp, _Abi>* __ptr, size_t __index) - : __ptr_(__ptr), __index_(__index) {} + __simd_mask_reference(__simd_mask_storage<_Tp, _Abi>* __ptr, size_t __index) : __ptr_(__ptr), __index_(__index) {} __simd_mask_reference(const __simd_mask_reference&) = default; @@ -940,8 +893,7 @@ public: }; template -constexpr decltype(_To{std::declval<_From>()}, true) -__is_non_narrowing_convertible_impl(_From) { +constexpr decltype(_To{std::declval<_From>()}, true) __is_non_narrowing_convertible_impl(_From) { return true; } @@ -951,17 +903,13 @@ constexpr bool __is_non_narrowing_convertible_impl(...) { } template -constexpr typename std::enable_if::value && - std::is_arithmetic<_From>::value, - bool>::type +constexpr typename std::enable_if::value && std::is_arithmetic<_From>::value, bool>::type __is_non_narrowing_arithmetic_convertible() { return __is_non_narrowing_convertible_impl<_To>(_From{}); } template -constexpr typename std::enable_if::value && - std::is_arithmetic<_From>::value), - bool>::type +constexpr typename std::enable_if::value && std::is_arithmetic<_From>::value), bool>::type __is_non_narrowing_arithmetic_convertible() { return false; } @@ -983,11 +931,11 @@ struct __nodeduce { template constexpr bool __vectorizable() { - return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && - !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; + return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && !std::is_volatile<_Tp>::value && + !std::is_same<_Tp, bool>::value; } -} +} // namespace athena::_simd namespace athena::_simd::simd_abi { using scalar = __simd_abi<_StorageKind::_Scalar, 1>; @@ -1006,11 +954,10 @@ template using native = __simd_abi<_StorageKind::_VecExt, 16 / sizeof(_Tp)>; #else template -using native = - fixed_size<_Tp, 16 / sizeof(_Tp)>; +using native = fixed_size<_Tp, 16 / sizeof(_Tp)>; #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION -} +} // namespace athena::_simd::simd_abi namespace athena::_simd { template > @@ -1032,8 +979,7 @@ template struct is_abi_tag : std::integral_constant {}; template <_StorageKind __kind, int _Np> -struct is_abi_tag<__simd_abi<__kind, _Np>> - : std::integral_constant {}; +struct is_abi_tag<__simd_abi<__kind, _Np>> : std::integral_constant {}; template struct is_simd : std::integral_constant {}; @@ -1045,23 +991,19 @@ template struct is_simd_mask : std::integral_constant {}; template -struct is_simd_mask> : std::integral_constant { -}; +struct is_simd_mask> : std::integral_constant {}; template struct is_simd_flag_type : std::integral_constant {}; template <> -struct is_simd_flag_type - : std::integral_constant {}; +struct is_simd_flag_type : std::integral_constant {}; template <> -struct is_simd_flag_type - : std::integral_constant {}; +struct is_simd_flag_type : std::integral_constant {}; template -struct is_simd_flag_type> - : std::integral_constant {}; +struct is_simd_flag_type> : std::integral_constant {}; template inline constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; @@ -1070,8 +1012,7 @@ inline constexpr bool is_simd_v = is_simd<_Tp>::value; template inline constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; template -inline constexpr bool is_simd_flag_type_v = - is_simd_flag_type<_Tp>::value; +inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value; template struct abi_for_size { using type = simd_abi::fixed_size<_Np>; @@ -1083,12 +1024,9 @@ template > struct simd_size; template -struct simd_size<_Tp, __simd_abi<__kind, _Np>> - : std::integral_constant { - static_assert( - std::is_arithmetic<_Tp>::value && - !std::is_same::type, bool>::value, - "Element type should be vectorizable"); +struct simd_size<_Tp, __simd_abi<__kind, _Np>> : std::integral_constant { + static_assert(std::is_arithmetic<_Tp>::value && !std::is_same::type, bool>::value, + "Element type should be vectorizable"); }; // TODO: implement it. @@ -1099,8 +1037,7 @@ template > inline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; template -inline constexpr size_t memory_alignment_v = - memory_alignment<_Tp, _Up>::value; +inline constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value; // class template simd [simd.class] template @@ -1125,50 +1062,41 @@ struct __static_simd_cast_traits { template struct __static_simd_cast_traits> { template - static typename std::enable_if::size() == - simd<_Tp, _NewAbi>::size(), - simd<_Tp, _NewAbi>>::type + static typename std::enable_if::size() == simd<_Tp, _NewAbi>::size(), simd<_Tp, _NewAbi>>::type __apply(const simd<_Up, _Abi>& __v); }; template struct __simd_cast_traits { template - static typename std::enable_if< - __is_non_narrowing_arithmetic_convertible<_Up, _Tp>(), - simd<_Tp, _Abi>>::type + static typename std::enable_if<__is_non_narrowing_arithmetic_convertible<_Up, _Tp>(), simd<_Tp, _Abi>>::type __apply(const simd<_Up, _Abi>& __v); }; template struct __simd_cast_traits> { template - static typename std::enable_if< - __is_non_narrowing_arithmetic_convertible<_Up, _Tp>() && - simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(), - simd<_Tp, _NewAbi>>::type + static typename std::enable_if<__is_non_narrowing_arithmetic_convertible<_Up, _Tp>() && + simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(), + simd<_Tp, _NewAbi>>::type __apply(const simd<_Up, _Abi>& __v); }; template -auto simd_cast(const simd<_Up, _Abi>& __v) - -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) { +auto simd_cast(const simd<_Up, _Abi>& __v) -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) { return __simd_cast_traits<_Tp>::__apply(__v); } template -auto static_simd_cast(const simd<_Up, _Abi>& __v) - -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) { +auto static_simd_cast(const simd<_Up, _Abi>& __v) -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) { return __static_simd_cast_traits<_Tp>::__apply(__v); } template -fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value> -to_fixed_size(const simd<_Tp, _Abi>&) noexcept; +fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value> to_fixed_size(const simd<_Tp, _Abi>&) noexcept; template -fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> -to_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept; +fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> to_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept; template native_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept; @@ -1186,26 +1114,21 @@ template tuple>...> split(const simd<_Tp, _Abi>&); template -tuple>...> -split(const simd_mask<_Tp, _Abi>&); +tuple>...> split(const simd_mask<_Tp, _Abi>&); template -array<_SimdType, simd_size::value / - _SimdType::size()> +array<_SimdType, simd_size::value / _SimdType::size()> split(const simd&); template -array<_SimdType, simd_size::value / - _SimdType::size()> +array<_SimdType, simd_size::value / _SimdType::size()> split(const simd_mask&); template -simd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> -concat(const simd<_Tp, _Abis>&...); +simd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> concat(const simd<_Tp, _Abis>&...); template -simd_mask<_Tp, - abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> +simd_mask<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> concat(const simd_mask<_Tp, _Abis>&...); // reductions [simd.mask.reductions] @@ -1239,23 +1162,20 @@ class where_expression; // masked assignment [simd.mask.where] template -where_expression, simd<_Tp, _Abi>> -where(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; +where_expression, simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&, + simd<_Tp, _Abi>&) noexcept; template -const_where_expression, const simd<_Tp, _Abi>> -where(const typename simd<_Tp, _Abi>::mask_type&, - const simd<_Tp, _Abi>&) noexcept; +const_where_expression, const simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&, + const simd<_Tp, _Abi>&) noexcept; template where_expression, simd_mask<_Tp, _Abi>> -where(const typename __nodeduce>::type&, - simd_mask<_Tp, _Abi>&) noexcept; +where(const typename __nodeduce>::type&, simd_mask<_Tp, _Abi>&) noexcept; template const_where_expression, const simd_mask<_Tp, _Abi>> -where(const typename __nodeduce>::type&, - const simd_mask<_Tp, _Abi>&) noexcept; +where(const typename __nodeduce>::type&, const simd_mask<_Tp, _Abi>&) noexcept; template where_expression where(bool, _Tp&) noexcept; @@ -1268,45 +1188,37 @@ template > _Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp()); template -typename _SimdType::value_type -reduce(const const_where_expression<_MaskType, _SimdType>&, - typename _SimdType::value_type neutral_element, _BinaryOp binary_op); +typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&, + typename _SimdType::value_type neutral_element, _BinaryOp binary_op); template -typename _SimdType::value_type -reduce(const const_where_expression<_MaskType, _SimdType>&, - plus binary_op = {}); +typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&, + plus binary_op = {}); template -typename _SimdType::value_type -reduce(const const_where_expression<_MaskType, _SimdType>&, - multiplies binary_op); +typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&, + multiplies binary_op); template -typename _SimdType::value_type -reduce(const const_where_expression<_MaskType, _SimdType>&, - bit_and binary_op); +typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&, + bit_and binary_op); template -typename _SimdType::value_type -reduce(const const_where_expression<_MaskType, _SimdType>&, - bit_or binary_op); +typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&, + bit_or binary_op); template -typename _SimdType::value_type -reduce(const const_where_expression<_MaskType, _SimdType>&, - bit_xor binary_op); +typename _SimdType::value_type reduce(const const_where_expression<_MaskType, _SimdType>&, + bit_xor binary_op); template _Tp hmin(const simd<_Tp, _Abi>&); template -typename _SimdType::value_type -hmin(const const_where_expression<_MaskType, _SimdType>&); +typename _SimdType::value_type hmin(const const_where_expression<_MaskType, _SimdType>&); template _Tp hmax(const simd<_Tp, _Abi>&); template -typename _SimdType::value_type -hmax(const const_where_expression<_MaskType, _SimdType>&); +typename _SimdType::value_type hmax(const const_where_expression<_MaskType, _SimdType>&); // algorithms [simd.alg] template @@ -1316,12 +1228,10 @@ template simd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; template -std::pair, simd<_Tp, _Abi>> -minmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; +std::pair, simd<_Tp, _Abi>> minmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; template -simd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&, - const simd<_Tp, _Abi>&); +simd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&); // [simd.whereexpr] // TODO implement where expressions. @@ -1387,6 +1297,7 @@ public: auto end() { return std::end(__data_); } auto begin() const { return std::begin(__data_); } auto end() const { return std::end(__data_); } + private: value_type __data_[_Simd::size()]; }; @@ -1396,6 +1307,7 @@ template class simd { template friend class simd; + public: using value_type = _Tp; using reference = __simd_reference<_Tp, _Tp, _Abi>; @@ -1406,34 +1318,25 @@ public: simd(const simd&) = default; simd& operator=(const simd&) = default; - static constexpr size_t size() noexcept { - return simd_size<_Tp, _Abi>::value; - } + static constexpr size_t size() noexcept { return simd_size<_Tp, _Abi>::value; } private: __simd_storage<_Tp, _Abi> __s_; template static constexpr bool __can_broadcast() { - return (std::is_arithmetic<_Up>::value && - __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) || - (!std::is_arithmetic<_Up>::value && - std::is_convertible<_Up, _Tp>::value) || + return (std::is_arithmetic<_Up>::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) || + (!std::is_arithmetic<_Up>::value && std::is_convertible<_Up, _Tp>::value) || std::is_same::type, int>::value || - (std::is_same::type, - unsigned int>::value && - std::is_unsigned<_Tp>::value); + (std::is_same::type, unsigned int>::value && std::is_unsigned<_Tp>::value); } template static constexpr decltype( - std::forward_as_tuple(std::declval<_Generator>()( - std::integral_constant())...), - bool()) + std::forward_as_tuple(std::declval<_Generator>()(std::integral_constant())...), bool()) __can_generate(std::index_sequence<__indicies...>) { return !__variadic_sum( - !__can_broadcast()( - std::integral_constant()))>()...); + !__can_broadcast()(std::integral_constant()))>()...); } template @@ -1443,9 +1346,7 @@ private: template void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { - int __not_used[]{((*this)[__indicies] = - __g(std::integral_constant()), - 0)...}; + int __not_used[]{((*this)[__indicies] = __g(std::integral_constant()), 0)...}; (void)__not_used; } @@ -1466,8 +1367,8 @@ public: #endif // implicit type conversion constructor template , __simd_storage<_Up, _UAbi>>::value>> + class = typename std::enable_if< + std::is_constructible<__simd_storage<_Tp, _Abi>, __simd_storage<_Up, _UAbi>>::value>> simd(const simd<_Up, _UAbi>& __v) : __s_(__v.__s_) {} #if 0 @@ -1489,29 +1390,20 @@ public: __s_.__broadcast(v); } #endif - simd(_Tp __rv) { - __s_.__broadcast(__rv); - } + simd(_Tp __rv) { __s_.__broadcast(__rv); } - simd(_Tp a, _Tp b, _Tp c = {}, _Tp d = {}) { - __s_.__set4(a, b, c, d); - } + simd(_Tp a, _Tp b, _Tp c = {}, _Tp d = {}) { __s_.__set4(a, b, c, d); } // generator constructor template (std::make_index_sequence()), - int>::type()> + int = typename std::enable_if<__can_generate<_Generator>(std::make_index_sequence()), int>::type()> explicit simd(_Generator&& __g) { - __generator_init(std::forward<_Generator>(__g), - std::make_index_sequence()); + __generator_init(std::forward<_Generator>(__g), std::make_index_sequence()); } // load constructor - template < - class _Up, class _Flags, - class = typename std::enable_if<__vectorizable<_Up>()>::type, - class = typename std::enable_if::value>::type> + template ()>::type, + class = typename std::enable_if::value>::type> simd(const _Up* __buffer, _Flags) { // TODO: optimize for overaligned flags for (size_t __i = 0; __i < size(); __i++) { @@ -1529,9 +1421,7 @@ public: } #endif // loads [simd.load] - void copy_from(const simd_data& __buffer) { - __s_.__copy_from(__buffer); - } + void copy_from(const simd_data& __buffer) { __s_.__copy_from(__buffer); } #if 0 // stores [simd.store] @@ -1546,9 +1436,7 @@ public: } #endif // stores [simd.store] - void copy_to(simd_data& __buffer) const { - __s_.__copy_to(__buffer); - } + void copy_to(simd_data& __buffer) const { __s_.__copy_to(__buffer); } // scalar access [simd.subscr] reference operator[](size_t __i) { return reference(&__s_, __i); } @@ -1606,7 +1494,7 @@ public: value_type dot3(const simd& other) const { return __s_.__dot3(other.__s_); } value_type dot4(const simd& other) const { return __s_.__dot4(other.__s_); } - template + template simd shuffle() const { simd s; s.__s_ = __s_.template __shuffle(); @@ -1624,9 +1512,7 @@ public: using reference = __simd_mask_reference<_Tp, _Abi>; using simd_type = simd<_Tp, _Abi>; using abi_type = _Abi; - static constexpr size_t size() noexcept { - return simd_size<_Tp, _Abi>::value; - } + static constexpr size_t size() noexcept { return simd_size<_Tp, _Abi>::value; } simd_mask() = default; // broadcast constructor @@ -1683,12 +1569,15 @@ public: }; template -inline simd_data<_Simd>::simd_data(const _Simd& s) { s.copy_to(*this); } +inline simd_data<_Simd>::simd_data(const _Simd& s) { + s.copy_to(*this); +} template class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { public: using storage_type = std::array<_Tp, __num_element>; + private: storage_type __storage_; @@ -1700,34 +1589,26 @@ private: public: _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; - void __set(size_t __index, _Tp __val) noexcept { - __storage_[__index] = __val; - } + void __set(size_t __index, _Tp __val) noexcept { __storage_[__index] = __val; } std::enable_if_t<__num_element >= 4> __set4(float a, float b, float c, float d) noexcept { __storage_[0] = a; __storage_[1] = b; __storage_[2] = c; __storage_[3] = d; } - void __broadcast(float __val) noexcept { - std::fill(__storage_.begin(), __storage_.end(), __val); - } + void __broadcast(float __val) noexcept { std::fill(__storage_.begin(), __storage_.end(), __val); } std::enable_if_t<__num_element >= 2, _Tp> __dot2(const __simd_storage& other) const noexcept { - return __storage_[0] * other.__storage_[0] + - __storage_[1] * other.__storage_[1]; + return __storage_[0] * other.__storage_[0] + __storage_[1] * other.__storage_[1]; } std::enable_if_t<__num_element >= 3, _Tp> __dot3(const __simd_storage& other) const noexcept { - return __storage_[0] * other.__storage_[0] + - __storage_[1] * other.__storage_[1] + + return __storage_[0] * other.__storage_[0] + __storage_[1] * other.__storage_[1] + __storage_[2] * other.__storage_[2]; } std::enable_if_t<__num_element >= 4, _Tp> __dot4(const __simd_storage& other) const noexcept { - return __storage_[0] * other.__storage_[0] + - __storage_[1] * other.__storage_[1] + - __storage_[2] * other.__storage_[2] + - __storage_[3] * other.__storage_[3]; + return __storage_[0] * other.__storage_[0] + __storage_[1] * other.__storage_[1] + + __storage_[2] * other.__storage_[2] + __storage_[3] * other.__storage_[3]; } - template + template std::enable_if_t<__num_element >= 4, __simd_storage> __shuffle() const noexcept { __simd_storage s; s.__storage_[0] = __storage_[x]; @@ -1756,13 +1637,10 @@ public: template class __simd_mask_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { std::bitset<__num_element> __storage_; + public: - bool __get(size_t __index) const noexcept { - return __storage_.test(__index); - } - void __set(size_t __index, bool __val) noexcept { - __storage_.set(__index, __val); - } + bool __get(size_t __index) const noexcept { return __storage_.test(__index); } + void __set(size_t __index, bool __val) noexcept { __storage_.set(__index, __val); } }; -} +} // namespace athena::_simd diff --git a/include/athena/simd/simd.hpp b/include/athena/simd/simd.hpp index 7873d1f..1ad5c92 100644 --- a/include/athena/simd/simd.hpp +++ b/include/athena/simd/simd.hpp @@ -1,6 +1,8 @@ #pragma once #define _ATHENA_SIMD_INCLUDED -namespace athena::_simd { using namespace std; } +namespace athena::_simd { +using namespace std; +} #include "parallelism_v2_simd.hpp" #if _M_IX86_FP >= 1 || _M_X64 #define __SSE__ 1 @@ -11,16 +13,23 @@ namespace athena::_simd { using namespace std; } #include "simd_sse.hpp" #else namespace simd_abi { -template struct athena_native {}; -template<> struct athena_native { using type = fixed_size<4>; }; -template<> struct athena_native { using type = fixed_size<4>; }; -} +template +struct athena_native {}; +template <> +struct athena_native { + using type = fixed_size<4>; +}; +template <> +struct athena_native { + using type = fixed_size<4>; +}; +} // namespace simd_abi #endif namespace athena { -template using simd = _simd::simd::type>; -template +template +using simd = _simd::simd::type>; +template using simd_values = _simd::simd_data>; using simd_floats = simd_values; using simd_doubles = simd_values; -} +} // namespace athena diff --git a/include/athena/simd/simd_avx.hpp b/include/athena/simd/simd_avx.hpp index 6bdc6b5..f7bdd49 100644 --- a/include/athena/simd/simd_avx.hpp +++ b/include/athena/simd/simd_avx.hpp @@ -6,7 +6,7 @@ #include namespace athena::_simd { // __m256d storage for AVX -template<> +template <> class __simd_storage { public: using storage_type = __m256d; @@ -22,12 +22,8 @@ public: sse_data[__index] = __val; __storage_ = _mm256_load_pd(sse_data.data()); } - void __set4(double a, double b, double c, double d) noexcept { - __storage_ = _mm256_set_pd(d, c, b, a); - } - void __broadcast(double __val) noexcept { - __storage_ = _mm256_set1_pd(__val); - } + void __set4(double a, double b, double c, double d) noexcept { __storage_ = _mm256_set_pd(d, c, b, a); } + void __broadcast(double __val) noexcept { __storage_ = _mm256_set1_pd(__val); } double __dot2(const __simd_storage& other) const noexcept { alignas(32) std::array sse_data; _mm256_store_pd(sse_data.data(), _mm256_mul_pd(__storage_, other.__storage_)); @@ -61,7 +57,7 @@ public: const storage_type& __native() const { return __storage_; } }; // __m256d mask storage for AVX -template<> +template <> class __simd_mask_storage : public __simd_storage { public: bool __get(size_t __index) const noexcept { @@ -83,95 +79,87 @@ inline simd simd::operator-() const { return _mm256_xor_pd(__s_.__storage_, _mm256_set1_pd(-0.0)); } -inline simd -operator+(const simd& a, const simd& b) { +inline simd operator+(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm256_add_pd(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd -operator-(const simd& a, const simd& b) { +inline simd operator-(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm256_sub_pd(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd -operator*(const simd& a, const simd& b) { +inline simd operator*(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm256_mul_pd(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd -operator/(const simd& a, const simd& b) { +inline simd operator/(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm256_div_pd(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd& -operator+=(simd& a, const simd& b) { +inline simd& operator+=(simd& a, const simd& b) { a.__s_.__storage_ = _mm256_add_pd(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd& -operator-=(simd& a, const simd& b) { +inline simd& operator-=(simd& a, const simd& b) { a.__s_.__storage_ = _mm256_sub_pd(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd& -operator*=(simd& a, const simd& b) { +inline simd& operator*=(simd& a, const simd& b) { a.__s_.__storage_ = _mm256_mul_pd(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd& -operator/=(simd& a, const simd& b) { +inline simd& operator/=(simd& a, const simd& b) { a.__s_.__storage_ = _mm256_div_pd(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd::mask_type -operator==(const simd& a, const simd& b) { +inline simd::mask_type operator==(const simd& a, + const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_EQ_OQ); return ret; } -inline simd::mask_type -operator!=(const simd& a, const simd& b) { +inline simd::mask_type operator!=(const simd& a, + const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_NEQ_OQ); return ret; } -inline simd::mask_type -operator>=(const simd& a, const simd& b) { +inline simd::mask_type operator>=(const simd& a, + const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_GE_OQ); return ret; } -inline simd::mask_type -operator<=(const simd& a, const simd& b) { +inline simd::mask_type operator<=(const simd& a, + const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_LE_OQ); return ret; } -inline simd::mask_type -operator>(const simd& a, const simd& b) { +inline simd::mask_type operator>(const simd& a, + const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_GT_OQ); return ret; } -inline simd::mask_type -operator<(const simd& a, const simd& b) { +inline simd::mask_type operator<(const simd& a, + const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm256_cmp_pd(a.__s_.__storage_, b.__s_.__storage_, _CMP_LT_OQ); return ret; @@ -182,7 +170,10 @@ inline __simd_storage::__simd_storage(const __simd_storage struct athena_native { using type = m256d_abi; }; +template <> +struct athena_native { + using type = m256d_abi; +}; } // namespace simd_abi } // namespace athena::_simd \ No newline at end of file diff --git a/include/athena/simd/simd_sse.hpp b/include/athena/simd/simd_sse.hpp index 8d59454..a7b62e5 100644 --- a/include/athena/simd/simd_sse.hpp +++ b/include/athena/simd/simd_sse.hpp @@ -40,12 +40,8 @@ public: sse_data[__index] = __val; __storage_ = _mm_load_ps(sse_data.data()); } - void __set4(float a, float b, float c, float d) noexcept { - __storage_ = _mm_set_ps(d, c, b, a); - } - void __broadcast(float __val) noexcept { - __storage_ = _mm_set1_ps(__val); - } + void __set4(float a, float b, float c, float d) noexcept { __storage_ = _mm_set_ps(d, c, b, a); } + void __broadcast(float __val) noexcept { __storage_ = _mm_set1_ps(__val); } float __dot2(const __simd_storage& other) const noexcept { #if __SSE4_1__ float ret; @@ -79,7 +75,7 @@ public: return sse_data[0] + sse_data[1] + sse_data[2] + sse_data[3]; #endif } - template + template __simd_storage __shuffle() const noexcept { __simd_storage s; s.__storage_ = _mm_shuffle_ps(__storage_, __storage_, _MM_SHUFFLE(w, z, y, x)); @@ -105,8 +101,7 @@ public: }; // __m128 mask storage for SSE2+ template <> -class __simd_mask_storage : public __simd_storage -{ +class __simd_mask_storage : public __simd_storage { public: bool __get(size_t __index) const noexcept { alignas(16) uint32_t sse_data[4]; @@ -126,95 +121,81 @@ inline simd simd::operator-() const { return _mm_xor_ps(__s_.__storage_, _mm_set1_ps(-0.f)); } -inline simd -operator+(const simd& a, const simd& b) { +inline simd operator+(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm_add_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd -operator-(const simd& a, const simd& b) { +inline simd operator-(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm_sub_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd -operator*(const simd& a, const simd& b) { +inline simd operator*(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm_mul_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd -operator/(const simd& a, const simd& b) { +inline simd operator/(const simd& a, const simd& b) { simd ret; ret.__s_.__storage_ = _mm_div_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd& -operator+=(simd& a, const simd& b) { +inline simd& operator+=(simd& a, const simd& b) { a.__s_.__storage_ = _mm_add_ps(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd& -operator-=(simd& a, const simd& b) { +inline simd& operator-=(simd& a, const simd& b) { a.__s_.__storage_ = _mm_sub_ps(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd& -operator*=(simd& a, const simd& b) { +inline simd& operator*=(simd& a, const simd& b) { a.__s_.__storage_ = _mm_mul_ps(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd& -operator/=(simd& a, const simd& b) { +inline simd& operator/=(simd& a, const simd& b) { a.__s_.__storage_ = _mm_div_ps(a.__s_.__storage_, b.__s_.__storage_); return a; } -inline simd::mask_type -operator==(const simd& a, const simd& b) { +inline simd::mask_type operator==(const simd& a, const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm_cmpeq_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd::mask_type -operator!=(const simd& a, const simd& b) { +inline simd::mask_type operator!=(const simd& a, const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm_cmpneq_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd::mask_type -operator>=(const simd& a, const simd& b) { +inline simd::mask_type operator>=(const simd& a, const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm_cmpge_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd::mask_type -operator<=(const simd& a, const simd& b) { +inline simd::mask_type operator<=(const simd& a, const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm_cmple_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd::mask_type -operator>(const simd& a, const simd& b) { +inline simd::mask_type operator>(const simd& a, const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm_cmpgt_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; } -inline simd::mask_type -operator<(const simd& a, const simd& b) { +inline simd::mask_type operator<(const simd& a, const simd& b) { simd::mask_type ret; ret.__s_.__storage_ = _mm_cmplt_ps(a.__s_.__storage_, b.__s_.__storage_); return ret; @@ -308,8 +289,7 @@ public: }; // __m128d mask storage for SSE2+ template <> -class __simd_mask_storage : public __simd_storage -{ +class __simd_mask_storage : public __simd_storage { public: bool __get(size_t __index) const noexcept { alignas(16) uint64_t sse_data[2]; @@ -332,108 +312,100 @@ inline simd simd::operator-() const { return ret; } -inline simd -operator+(const simd& a, const simd& b) { +inline simd operator+(const simd& a, const simd& b) { simd ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_add_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd -operator-(const simd& a, const simd& b) { +inline simd operator-(const simd& a, const simd& b) { simd ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_sub_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd -operator*(const simd& a, const simd& b) { +inline simd operator*(const simd& a, const simd& b) { simd ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_mul_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd -operator/(const simd& a, const simd& b) { +inline simd operator/(const simd& a, const simd& b) { simd ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_div_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd& -operator+=(simd& a, const simd& b) { +inline simd& operator+=(simd& a, const simd& b) { for (int i = 0; i < 2; ++i) a.__s_.__storage_[i] = _mm_add_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return a; } -inline simd& -operator-=(simd& a, const simd& b) { +inline simd& operator-=(simd& a, const simd& b) { for (int i = 0; i < 2; ++i) a.__s_.__storage_[i] = _mm_sub_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return a; } -inline simd& -operator*=(simd& a, const simd& b) { +inline simd& operator*=(simd& a, const simd& b) { for (int i = 0; i < 2; ++i) a.__s_.__storage_[i] = _mm_mul_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return a; } -inline simd& -operator/=(simd& a, const simd& b) { +inline simd& operator/=(simd& a, const simd& b) { for (int i = 0; i < 2; ++i) a.__s_.__storage_[i] = _mm_div_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return a; } -inline simd::mask_type -operator==(const simd& a, const simd& b) { +inline simd::mask_type operator==(const simd& a, + const simd& b) { simd::mask_type ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_cmpeq_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd::mask_type -operator!=(const simd& a, const simd& b) { +inline simd::mask_type operator!=(const simd& a, + const simd& b) { simd::mask_type ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_cmpneq_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd::mask_type -operator>=(const simd& a, const simd& b) { +inline simd::mask_type operator>=(const simd& a, + const simd& b) { simd::mask_type ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_cmpge_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd::mask_type -operator<=(const simd& a, const simd& b) { +inline simd::mask_type operator<=(const simd& a, + const simd& b) { simd::mask_type ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_cmple_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd::mask_type -operator>(const simd& a, const simd& b) { +inline simd::mask_type operator>(const simd& a, + const simd& b) { simd::mask_type ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_cmpgt_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); return ret; } -inline simd::mask_type -operator<(const simd& a, const simd& b) { +inline simd::mask_type operator<(const simd& a, + const simd& b) { simd::mask_type ret; for (int i = 0; i < 2; ++i) ret.__s_.__storage_[i] = _mm_cmplt_pd(a.__s_.__storage_[i], b.__s_.__storage_[i]); @@ -445,10 +417,17 @@ inline __simd_storage::__simd_storage(const __simd_storage struct athena_native {}; -template<> struct athena_native { using type = m128_abi; }; +template +struct athena_native {}; +template <> +struct athena_native { + using type = m128_abi; +}; #ifndef __AVX__ -template<> struct athena_native { using type = m128d_abi; }; +template <> +struct athena_native { + using type = m128d_abi; +}; #endif } // namespace simd_abi diff --git a/include/bn.hpp b/include/bn.hpp index 37b28f1..89ce4c7 100644 --- a/include/bn.hpp +++ b/include/bn.hpp @@ -1,13 +1,11 @@ #pragma once #include "athena/Types.hpp" -namespace bignum -{ +namespace bignum { int compare(const atUint8* a, const atUint8* b, atUint32 n); void subModulus(atUint8* a, const atUint8* N, atUint32 n); void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n); void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n); void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en); void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n); -} - +} // namespace bignum diff --git a/include/ec.hpp b/include/ec.hpp index db0059a..810f3ca 100644 --- a/include/ec.hpp +++ b/include/ec.hpp @@ -1,11 +1,8 @@ #pragma once #include "athena/Types.hpp" -namespace ecc -{ +namespace ecc { void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid); void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId); void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash); -} - - +} // namespace ecc diff --git a/include/optional.hpp b/include/optional.hpp index 2955d04..14eb2ef 100644 --- a/include/optional.hpp +++ b/include/optional.hpp @@ -7,151 +7,148 @@ // The idea and interface is based on Boost.Optional library // authored by Fernando Luis Cacciola Carballal -# ifndef ___OPTIONAL_HPP___ -# define ___OPTIONAL_HPP___ +#ifndef ___OPTIONAL_HPP___ +#define ___OPTIONAL_HPP___ -# include -# include -# include -# include -# include -# include -# include "athena/Global.hpp" +#include +#include +#include +#include +#include +#include +#include "athena/Global.hpp" -# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false +#define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false -# if defined __GNUC__ // NOTE: GNUC is also defined for Clang -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# endif +#if defined __GNUC__ // NOTE: GNUC is also defined for Clang +#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +#define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +#elif (__GNUC__ > 4) +#define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +#endif # -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# endif +#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +#define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +#elif (__GNUC__ > 4) +#define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +#endif # -# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# endif -# endif +#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +#define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +#elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +#define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +#elif (__GNUC__ > 4) +#define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +#endif +#endif # -# if defined __clang_major__ -# if (__clang_major__ == 3 && __clang_minor__ >= 5) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# elif (__clang_major__ > 3) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# endif -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# endif -# endif +#if defined __clang_major__ +#if (__clang_major__ == 3 && __clang_minor__ >= 5) +#define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +#elif (__clang_major__ > 3) +#define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +#endif +#if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +#define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +#elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +#define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +#endif +#endif # -# if defined _MSC_VER -# if (_MSC_VER >= 1900) -# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# endif -# endif +#if defined _MSC_VER +#if (_MSC_VER >= 1900) +#define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +#endif +#endif -# if defined __clang__ -# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif -# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif +#if defined __clang__ +#if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +#define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +#else +#define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +#endif +#elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +#define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +#elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +#define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +#else +#define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +#endif +#if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +#define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +#define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +#else +#define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +#define OPTIONAL_CONSTEXPR_INIT_LIST +#endif -# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 -# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr -# else -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 -# define OPTIONAL_CONSTEXPR_INIT_LIST -# endif +#if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) +#define OPTIONAL_HAS_MOVE_ACCESSORS 1 +#else +#define OPTIONAL_HAS_MOVE_ACCESSORS 0 +#endif -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) -# define OPTIONAL_HAS_MOVE_ACCESSORS 1 -# else -# define OPTIONAL_HAS_MOVE_ACCESSORS 0 -# endif +#// In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +#if (defined __cplusplus) && (__cplusplus == 201103L) +#define OPTIONAL_MUTABLE_CONSTEXPR +#else +#define OPTIONAL_MUTABLE_CONSTEXPR constexpr +#endif -# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr -# if (defined __cplusplus) && (__cplusplus == 201103L) -# define OPTIONAL_MUTABLE_CONSTEXPR -# else -# define OPTIONAL_MUTABLE_CONSTEXPR constexpr -# endif +namespace std { -namespace std{ - -namespace experimental{ +namespace experimental { // BEGIN workaround for missing is_trivially_destructible -# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it: it is already there -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - template - using is_trivially_destructible = std::has_trivial_destructor; -# endif +#if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +// leave it: it is already there +#elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +// leave it: it is already there +#elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +// leave it: it is already there +#elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS +// leave it: the user doesn't want it +#else +template +using is_trivially_destructible = std::has_trivial_destructor; +#endif // END workaround for missing is_trivially_destructible -# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - +#if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) +// leave it; our metafunctions are already defined. +#elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +// leave it; our metafunctions are already defined. +#elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +// leave it: it is already there +#elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS +// leave it: the user doesn't want it +#else // workaround for missing traits in GCC and CLANG template -struct is_nothrow_move_constructible -{ +struct is_nothrow_move_constructible { constexpr static bool value = std::is_nothrow_constructible::value; }; - template -struct is_assignable -{ +struct is_assignable { template - constexpr static bool has_assign(...) { return false; } + constexpr static bool has_assign(...) { + return false; + } - template () = std::declval(), true)) > + template () = std::declval(), true))> // the comma operator is necessary for the cases where operator= returns void - constexpr static bool has_assign(bool) { return true; } + constexpr static bool has_assign(bool) { + return true; + } constexpr static bool value = has_assign(true); }; - template -struct is_nothrow_move_assignable -{ +struct is_nothrow_move_assignable { template struct has_nothrow_move_assign { constexpr static bool value = false; @@ -159,102 +156,96 @@ struct is_nothrow_move_assignable template struct has_nothrow_move_assign { - constexpr static bool value = noexcept( std::declval() = std::declval() ); + constexpr static bool value = noexcept(std::declval() = std::declval()); }; constexpr static bool value = has_nothrow_move_assign::value>::value; }; // end workaround - -# endif - - +#endif // 20.5.4, optional for object types -template class optional; +template +class optional; // 20.5.5, optional for lvalue reference types -template class optional; - +template +class optional; // workaround: std utility functions aren't constexpr yet -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept -{ +template +inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept { return static_cast(t); } -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, "!!"); - return static_cast(t); +template +inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept { + static_assert(!std::is_lvalue_reference::value, "!!"); + return static_cast(t); } -template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept -{ - return static_cast::type&&>(t); +template +inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept { + return static_cast::type&&>(t); } - #if defined NDEBUG -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) #else -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([] { assert(!#CHECK); }(), (EXPR))) #endif - -namespace detail_ -{ +namespace detail_ { // static_addressof: a constexpr version of addressof template -struct has_overloaded_addressof -{ +struct has_overloaded_addressof { template - constexpr static bool has_overload(...) { return false; } + constexpr static bool has_overload(...) { + return false; + } - template ().operator&()) > - constexpr static bool has_overload(bool) { return true; } + template ().operator&())> + constexpr static bool has_overload(bool) { + return true; + } constexpr static bool value = has_overload(true); }; template )> -constexpr T* static_addressof(T& ref) -{ +constexpr T* static_addressof(T& ref) { return &ref; } template )> -T* static_addressof(T& ref) -{ +T* static_addressof(T& ref) { return std::addressof(ref); } - // the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A template -U convert(U v) { return v; } +U convert(U v) { + return v; +} -} // namespace detail - - -constexpr struct trivial_init_t{} trivial_init{}; +} // namespace detail_ +constexpr struct trivial_init_t { +} trivial_init{}; // 20.5.6, In-place construction -constexpr struct in_place_t{} in_place{}; - +constexpr struct in_place_t { +} in_place{}; // 20.5.7, Disengaged state indicator -struct nullopt_t -{ - struct init{}; - constexpr explicit nullopt_t(init){} +struct nullopt_t { + struct init {}; + constexpr explicit nullopt_t(init) {} }; constexpr nullopt_t nullopt{nullopt_t::init()}; - // 20.5.8, class bad_optional_access class bad_optional_access : public logic_error { public: @@ -262,132 +253,120 @@ public: explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} }; - template -union storage_t -{ +union storage_t { unsigned char dummy_; T value_; - constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; + constexpr storage_t(trivial_init_t) noexcept : dummy_(){}; template - constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + constexpr storage_t(Args&&... args) : value_(constexpr_forward(args)...) {} - ~storage_t(){} -}; - - -template -union constexpr_storage_t -{ - unsigned char dummy_; - T value_; - - constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~constexpr_storage_t() = default; -}; - - -template -struct optional_base -{ - bool init_; - storage_t storage_; - - constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~optional_base() { if (init_) storage_.value_.T::~T(); } -}; - - -template -struct constexpr_optional_base -{ - bool init_; - constexpr_storage_t storage_; - - constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~constexpr_optional_base() = default; + ~storage_t() {} }; template -using OptionalBase = typename std::conditional< - is_trivially_destructible::value, - constexpr_optional_base, - optional_base ->::type; +union constexpr_storage_t { + unsigned char dummy_; + T value_; + constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_(){}; + template + constexpr constexpr_storage_t(Args&&... args) : value_(constexpr_forward(args)...) {} + + ~constexpr_storage_t() = default; +}; template -class optional : private OptionalBase -{ - static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); - static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); +struct optional_base { + bool init_; + storage_t storage_; + constexpr optional_base() noexcept : init_(false), storage_(trivial_init){}; + + explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template + explicit optional_base(in_place_t, Args&&... args) : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~optional_base() { + if (init_) + storage_.value_.T::~T(); + } +}; + +template +struct constexpr_optional_base { + bool init_; + constexpr_storage_t storage_; + + constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init){}; + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template + explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~constexpr_optional_base() = default; +}; + +template +using OptionalBase = + typename std::conditional::value, constexpr_optional_base, optional_base>::type; + +template +class optional : private OptionalBase { + static_assert(!std::is_same::type, nullopt_t>::value, "bad T"); + static_assert(!std::is_same::type, in_place_t>::value, "bad T"); constexpr bool initialized() const noexcept { return OptionalBase::init_; } - T* dataptr() { return std::addressof(OptionalBase::storage_.value_); } + T* dataptr() { return std::addressof(OptionalBase::storage_.value_); } constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); } -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 +#if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 +#if OPTIONAL_HAS_MOVE_ACCESSORS == 1 OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage_.value_; } -# else +#else T& contained_val() & { return OptionalBase::storage_.value_; } T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } -# endif -# else +#endif +#else constexpr const T& contained_val() const { return OptionalBase::storage_.value_; } T& contained_val() { return OptionalBase::storage_.value_; } -# endif +#endif void clear() noexcept { - if (initialized()) dataptr()->T::~T(); + if (initialized()) + dataptr()->T::~T(); OptionalBase::init_ = false; } template - void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) - { + void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) { assert(!OptionalBase::init_); ::new (static_cast(dataptr())) T(std::forward(args)...); OptionalBase::init_ = true; } template - void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) - { + void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) { assert(!OptionalBase::init_); ::new (static_cast(dataptr())) T(il, std::forward(args)...); OptionalBase::init_ = true; @@ -397,24 +376,20 @@ public: typedef T value_type; // 20.5.5.1, constructors - constexpr optional() noexcept : OptionalBase() {}; - constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + constexpr optional() noexcept : OptionalBase(){}; + constexpr optional(nullopt_t) noexcept : OptionalBase(){}; - optional(const optional& rhs) - : OptionalBase() - { + optional(const optional& rhs) : OptionalBase() { if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(*rhs); - OptionalBase::init_ = true; + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; } } - optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value) - : OptionalBase() - { + optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value) : OptionalBase() { if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(std::move(*rhs)); - OptionalBase::init_ = true; + ::new (static_cast(dataptr())) T(std::move(*rhs)); + OptionalBase::init_ = true; } } @@ -434,122 +409,123 @@ public: ~optional() = default; // 20.5.4.3, assignment - optional& operator=(nullopt_t) noexcept - { + optional& operator=(nullopt_t) noexcept { clear(); return *this; } - optional& operator=(const optional& rhs) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); - else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + optional& operator=(const optional& rhs) { + if (initialized() == true && rhs.initialized() == false) + clear(); + else if (initialized() == false && rhs.initialized() == true) + initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) + contained_val() = *rhs; return *this; } - optional& operator=(optional&& rhs) - noexcept(is_nothrow_move_assignable::value && is_nothrow_move_constructible::value) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); - else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); + optional& + operator=(optional&& rhs) noexcept(is_nothrow_move_assignable::value&& is_nothrow_move_constructible::value) { + if (initialized() == true && rhs.initialized() == false) + clear(); + else if (initialized() == false && rhs.initialized() == true) + initialize(std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) + contained_val() = std::move(*rhs); return *this; } template - auto operator=(U&& v) - -> typename enable_if - < - is_same::type, T>::value, - optional& - >::type - { - if (initialized()) { contained_val() = std::forward(v); } - else { initialize(std::forward(v)); } + auto operator=(U&& v) -> typename enable_if::type, T>::value, optional&>::type { + if (initialized()) { + contained_val() = std::forward(v); + } else { + initialize(std::forward(v)); + } return *this; } - template - void emplace(Args&&... args) - { + void emplace(Args&&... args) { clear(); initialize(std::forward(args)...); } template - void emplace(initializer_list il, Args&&... args) - { + void emplace(initializer_list il, Args&&... args) { clear(); initialize(il, std::forward(args)...); } // 20.5.4.4, Swap - void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value && noexcept(swap(declval(), declval()))) - { - if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } - else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } - else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } + void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value&& noexcept(swap(declval(), + declval()))) { + if (initialized() == true && rhs.initialized() == false) { + rhs.initialize(std::move(**this)); + clear(); + } else if (initialized() == false && rhs.initialized() == true) { + initialize(std::move(*rhs)); + rhs.clear(); + } else if (initialized() == true && rhs.initialized() == true) { + using std::swap; + swap(**this, *rhs); + } } // 20.5.4.5, Observers explicit constexpr operator bool() const noexcept { return initialized(); } - constexpr T const* operator ->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); - } + constexpr T const* operator->() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 +#if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { - assert (initialized()); + OPTIONAL_MUTABLE_CONSTEXPR T* operator->() { + assert(initialized()); return dataptr(); } - constexpr T const& operator *() const& { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } + constexpr T const& operator*() const& { return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); } - OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { - assert (initialized()); + OPTIONAL_MUTABLE_CONSTEXPR T& operator*() & { + assert(initialized()); return contained_val(); } - OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { - assert (initialized()); + OPTIONAL_MUTABLE_CONSTEXPR T&& operator*() && { + assert(initialized()); return constexpr_move(contained_val()); } constexpr T const& value() const& { - if (!initialized()) atFatal("bad optional access"); + if (!initialized()) + atFatal("bad optional access"); return contained_val(); } OPTIONAL_MUTABLE_CONSTEXPR T& value() & { - if (!initialized()) atFatal("bad optional access"); + if (!initialized()) + atFatal("bad optional access"); return contained_val(); } OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { - if (!initialized()) atFatal("bad optional access"); + if (!initialized()) + atFatal("bad optional access"); return std::move(contained_val()); } -# else +#else - T* operator ->() { - assert (initialized()); + T* operator->() { + assert(initialized()); return dataptr(); } - constexpr T const& operator *() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } + constexpr T const& operator*() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); } - T& operator *() { - assert (initialized()); + T& operator*() { + assert(initialized()); return contained_val(); } @@ -565,56 +541,50 @@ public: return contained_val(); } -# endif +#endif -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 +#if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 template - constexpr T value_or(V&& v) const& - { + constexpr T value_or(V&& v) const& { return *this ? **this : detail_::convert(constexpr_forward(v)); } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 +#if OPTIONAL_HAS_MOVE_ACCESSORS == 1 template - OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) + : detail_::convert(constexpr_forward(v)); } -# else +#else template - T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + T value_or(V&& v) && { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) + : detail_::convert(constexpr_forward(v)); } -# endif +#endif -# else +#else template - constexpr T value_or(V&& v) const - { + constexpr T value_or(V&& v) const { return *this ? **this : detail_::convert(constexpr_forward(v)); } -# endif - +#endif }; - template -class optional -{ - static_assert( !std::is_same::value, "bad T" ); - static_assert( !std::is_same::value, "bad T" ); +class optional { + static_assert(!std::is_same::value, "bad T"); + static_assert(!std::is_same::value, "bad T"); T* ref; public: - // 20.5.5.1, construction/destruction constexpr optional() noexcept : ref(nullptr) {} @@ -639,411 +609,373 @@ public: } // optional& operator=(const optional& rhs) noexcept { - // ref = rhs.ref; - // return *this; + // ref = rhs.ref; + // return *this; // } // optional& operator=(optional&& rhs) noexcept { - // ref = rhs.ref; - // return *this; + // ref = rhs.ref; + // return *this; // } template - auto operator=(U&& rhs) noexcept - -> typename enable_if - < - is_same::type, optional>::value, - optional& - >::type - { + auto operator=(U&& rhs) noexcept -> + typename enable_if::type, optional>::value, optional&>::type { ref = rhs.ref; return *this; } template - auto operator=(U&& rhs) noexcept - -> typename enable_if - < - !is_same::type, optional>::value, - optional& - >::type - = delete; + auto operator=(U&& rhs) noexcept -> + typename enable_if::type, optional>::value, optional&>::type = delete; - void emplace(T& v) noexcept { - ref = detail_::static_addressof(v); - } + void emplace(T& v) noexcept { ref = detail_::static_addressof(v); } void emplace(T&&) = delete; - - void swap(optional& rhs) noexcept - { - std::swap(ref, rhs.ref); - } + void swap(optional& rhs) noexcept { std::swap(ref, rhs.ref); } // 20.5.5.3, observers - constexpr T* operator->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); - } + constexpr T* operator->() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); } - constexpr T& operator*() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); - } + constexpr T& operator*() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); } constexpr T& value() const { - if (!ref) atFatal("bad optional access"); + if (!ref) + atFatal("bad optional access"); return *ref; } - explicit constexpr operator bool() const noexcept { - return ref != nullptr; - } + explicit constexpr operator bool() const noexcept { return ref != nullptr; } template - constexpr typename decay::type value_or(V&& v) const - { + constexpr typename decay::type value_or(V&& v) const { return *this ? **this : detail_::convert::type>(constexpr_forward(v)); } }; - template -class optional -{ - static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); +class optional { + static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); }; - // 20.5.8, Relational operators -template constexpr bool operator==(const optional& x, const optional& y) -{ +template +constexpr bool operator==(const optional& x, const optional& y) { return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; } -template constexpr bool operator!=(const optional& x, const optional& y) -{ +template +constexpr bool operator!=(const optional& x, const optional& y) { return !(x == y); } -template constexpr bool operator<(const optional& x, const optional& y) -{ +template +constexpr bool operator<(const optional& x, const optional& y) { return (!y) ? false : (!x) ? true : *x < *y; } -template constexpr bool operator>(const optional& x, const optional& y) -{ +template +constexpr bool operator>(const optional& x, const optional& y) { return (y < x); } -template constexpr bool operator<=(const optional& x, const optional& y) -{ +template +constexpr bool operator<=(const optional& x, const optional& y) { return !(y < x); } -template constexpr bool operator>=(const optional& x, const optional& y) -{ +template +constexpr bool operator>=(const optional& x, const optional& y) { return !(x < y); } - // 20.5.9, Comparison with nullopt -template constexpr bool operator==(const optional& x, nullopt_t) noexcept -{ +template +constexpr bool operator==(const optional& x, nullopt_t) noexcept { return (!x); } -template constexpr bool operator==(nullopt_t, const optional& x) noexcept -{ +template +constexpr bool operator==(nullopt_t, const optional& x) noexcept { return (!x); } -template constexpr bool operator!=(const optional& x, nullopt_t) noexcept -{ +template +constexpr bool operator!=(const optional& x, nullopt_t) noexcept { return bool(x); } -template constexpr bool operator!=(nullopt_t, const optional& x) noexcept -{ +template +constexpr bool operator!=(nullopt_t, const optional& x) noexcept { return bool(x); } -template constexpr bool operator<(const optional&, nullopt_t) noexcept -{ +template +constexpr bool operator<(const optional&, nullopt_t) noexcept { return false; } -template constexpr bool operator<(nullopt_t, const optional& x) noexcept -{ +template +constexpr bool operator<(nullopt_t, const optional& x) noexcept { return bool(x); } -template constexpr bool operator<=(const optional& x, nullopt_t) noexcept -{ +template +constexpr bool operator<=(const optional& x, nullopt_t) noexcept { return (!x); } -template constexpr bool operator<=(nullopt_t, const optional&) noexcept -{ +template +constexpr bool operator<=(nullopt_t, const optional&) noexcept { return true; } -template constexpr bool operator>(const optional& x, nullopt_t) noexcept -{ +template +constexpr bool operator>(const optional& x, nullopt_t) noexcept { return bool(x); } -template constexpr bool operator>(nullopt_t, const optional&) noexcept -{ +template +constexpr bool operator>(nullopt_t, const optional&) noexcept { return false; } -template constexpr bool operator>=(const optional&, nullopt_t) noexcept -{ +template +constexpr bool operator>=(const optional&, nullopt_t) noexcept { return true; } -template constexpr bool operator>=(nullopt_t, const optional& x) noexcept -{ +template +constexpr bool operator>=(nullopt_t, const optional& x) noexcept { return (!x); } - - // 20.5.10, Comparison with T -template constexpr bool operator==(const optional& x, const T& v) -{ +template +constexpr bool operator==(const optional& x, const T& v) { return bool(x) ? *x == v : false; } -template constexpr bool operator==(const T& v, const optional& x) -{ +template +constexpr bool operator==(const T& v, const optional& x) { return bool(x) ? v == *x : false; } -template constexpr bool operator!=(const optional& x, const T& v) -{ +template +constexpr bool operator!=(const optional& x, const T& v) { return bool(x) ? *x != v : true; } -template constexpr bool operator!=(const T& v, const optional& x) -{ +template +constexpr bool operator!=(const T& v, const optional& x) { return bool(x) ? v != *x : true; } -template constexpr bool operator<(const optional& x, const T& v) -{ +template +constexpr bool operator<(const optional& x, const T& v) { return bool(x) ? *x < v : true; } -template constexpr bool operator>(const T& v, const optional& x) -{ +template +constexpr bool operator>(const T& v, const optional& x) { return bool(x) ? v > *x : true; } -template constexpr bool operator>(const optional& x, const T& v) -{ +template +constexpr bool operator>(const optional& x, const T& v) { return bool(x) ? *x > v : false; } -template constexpr bool operator<(const T& v, const optional& x) -{ +template +constexpr bool operator<(const T& v, const optional& x) { return bool(x) ? v < *x : false; } -template constexpr bool operator>=(const optional& x, const T& v) -{ +template +constexpr bool operator>=(const optional& x, const T& v) { return bool(x) ? *x >= v : false; } -template constexpr bool operator<=(const T& v, const optional& x) -{ +template +constexpr bool operator<=(const T& v, const optional& x) { return bool(x) ? v <= *x : false; } -template constexpr bool operator<=(const optional& x, const T& v) -{ +template +constexpr bool operator<=(const optional& x, const T& v) { return bool(x) ? *x <= v : true; } -template constexpr bool operator>=(const T& v, const optional& x) -{ +template +constexpr bool operator>=(const T& v, const optional& x) { return bool(x) ? v >= *x : true; } - // Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ +template +constexpr bool operator==(const optional& x, const T& v) { return bool(x) ? *x == v : false; } -template constexpr bool operator==(const T& v, const optional& x) -{ +template +constexpr bool operator==(const T& v, const optional& x) { return bool(x) ? v == *x : false; } -template constexpr bool operator!=(const optional& x, const T& v) -{ +template +constexpr bool operator!=(const optional& x, const T& v) { return bool(x) ? *x != v : true; } -template constexpr bool operator!=(const T& v, const optional& x) -{ +template +constexpr bool operator!=(const T& v, const optional& x) { return bool(x) ? v != *x : true; } -template constexpr bool operator<(const optional& x, const T& v) -{ +template +constexpr bool operator<(const optional& x, const T& v) { return bool(x) ? *x < v : true; } -template constexpr bool operator>(const T& v, const optional& x) -{ +template +constexpr bool operator>(const T& v, const optional& x) { return bool(x) ? v > *x : true; } -template constexpr bool operator>(const optional& x, const T& v) -{ +template +constexpr bool operator>(const optional& x, const T& v) { return bool(x) ? *x > v : false; } -template constexpr bool operator<(const T& v, const optional& x) -{ +template +constexpr bool operator<(const T& v, const optional& x) { return bool(x) ? v < *x : false; } -template constexpr bool operator>=(const optional& x, const T& v) -{ +template +constexpr bool operator>=(const optional& x, const T& v) { return bool(x) ? *x >= v : false; } -template constexpr bool operator<=(const T& v, const optional& x) -{ +template +constexpr bool operator<=(const T& v, const optional& x) { return bool(x) ? v <= *x : false; } -template constexpr bool operator<=(const optional& x, const T& v) -{ +template +constexpr bool operator<=(const optional& x, const T& v) { return bool(x) ? *x <= v : true; } -template constexpr bool operator>=(const T& v, const optional& x) -{ +template +constexpr bool operator>=(const T& v, const optional& x) { return bool(x) ? v >= *x : true; } // Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ +template +constexpr bool operator==(const optional& x, const T& v) { return bool(x) ? *x == v : false; } -template constexpr bool operator==(const T& v, const optional& x) -{ +template +constexpr bool operator==(const T& v, const optional& x) { return bool(x) ? v == *x : false; } -template constexpr bool operator!=(const optional& x, const T& v) -{ +template +constexpr bool operator!=(const optional& x, const T& v) { return bool(x) ? *x != v : true; } -template constexpr bool operator!=(const T& v, const optional& x) -{ +template +constexpr bool operator!=(const T& v, const optional& x) { return bool(x) ? v != *x : true; } -template constexpr bool operator<(const optional& x, const T& v) -{ +template +constexpr bool operator<(const optional& x, const T& v) { return bool(x) ? *x < v : true; } -template constexpr bool operator>(const T& v, const optional& x) -{ +template +constexpr bool operator>(const T& v, const optional& x) { return bool(x) ? v > *x : true; } -template constexpr bool operator>(const optional& x, const T& v) -{ +template +constexpr bool operator>(const optional& x, const T& v) { return bool(x) ? *x > v : false; } -template constexpr bool operator<(const T& v, const optional& x) -{ +template +constexpr bool operator<(const T& v, const optional& x) { return bool(x) ? v < *x : false; } -template constexpr bool operator>=(const optional& x, const T& v) -{ +template +constexpr bool operator>=(const optional& x, const T& v) { return bool(x) ? *x >= v : false; } -template constexpr bool operator<=(const T& v, const optional& x) -{ +template +constexpr bool operator<=(const T& v, const optional& x) { return bool(x) ? v <= *x : false; } -template constexpr bool operator<=(const optional& x, const T& v) -{ +template +constexpr bool operator<=(const optional& x, const T& v) { return bool(x) ? *x <= v : true; } -template constexpr bool operator>=(const T& v, const optional& x) -{ +template +constexpr bool operator>=(const T& v, const optional& x) { return bool(x) ? v >= *x : true; } - // 20.5.12, Specialized algorithms template -void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) -{ +void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } - template -constexpr optional::type> make_optional(T&& v) -{ +constexpr optional::type> make_optional(T&& v) { return optional::type>(constexpr_forward(v)); } template -constexpr optional make_optional(reference_wrapper v) -{ +constexpr optional make_optional(reference_wrapper v) { return optional(v.get()); } - } // namespace experimental } // namespace std -namespace std -{ - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef std::experimental::optional argument_type; +namespace std { +template +struct hash> { + typedef typename hash::result_type result_type; + typedef std::experimental::optional argument_type; - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } +}; - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef std::experimental::optional argument_type; +template +struct hash> { + typedef typename hash::result_type result_type; + typedef std::experimental::optional argument_type; - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; -} + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } +}; +} // namespace std -# undef TR2_OPTIONAL_REQUIRES -# undef TR2_OPTIONAL_ASSERTED_EXPRESSION +#undef TR2_OPTIONAL_REQUIRES +#undef TR2_OPTIONAL_ASSERTED_EXPRESSION -# endif //___OPTIONAL_HPP___ +#endif //___OPTIONAL_HPP___ diff --git a/src/LZ77/LZBase.cpp b/src/LZ77/LZBase.cpp index 05bb6f4..c404f1c 100644 --- a/src/LZ77/LZBase.cpp +++ b/src/LZ77/LZBase.cpp @@ -1,47 +1,32 @@ #include "LZ77/LZLookupTable.hpp" #include "LZ77/LZBase.hpp" - LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) - : m_slidingWindow(slidingWindow), - m_readAheadBuffer(minimumMatch), - m_minMatch(minimumMatch), - m_blockSize(blockSize), - m_minOffset(minimumOffset) -{ -} +: m_slidingWindow(slidingWindow) +, m_readAheadBuffer(minimumMatch) +, m_minMatch(minimumMatch) +, m_blockSize(blockSize) +, m_minOffset(minimumOffset) {} -void LZBase::setSlidingWindow(atInt32 slidingWindow) -{ - m_slidingWindow = slidingWindow; -} +void LZBase::setSlidingWindow(atInt32 slidingWindow) { m_slidingWindow = slidingWindow; } -atInt32 LZBase::slidingWindow() {return m_slidingWindow;} +atInt32 LZBase::slidingWindow() { return m_slidingWindow; } -void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer) -{ - m_readAheadBuffer = readAheadBuffer; -} +void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer) { m_readAheadBuffer = readAheadBuffer; } -atInt32 LZBase::readAheadBuffer() {return m_readAheadBuffer;} +atInt32 LZBase::readAheadBuffer() { return m_readAheadBuffer; } -void LZBase::setMinMatch(atInt32 minimumMatch) { m_minMatch = minimumMatch;} +void LZBase::setMinMatch(atInt32 minimumMatch) { m_minMatch = minimumMatch; } -atInt32 LZBase::minMatch() {return m_minMatch;} +atInt32 LZBase::minMatch() { return m_minMatch; } -void LZBase::setBlockSize(atInt32 blockSize) -{ - m_blockSize = blockSize ; -} +void LZBase::setBlockSize(atInt32 blockSize) { m_blockSize = blockSize; } -atInt32 LZBase::blockSize() {return m_blockSize;} +atInt32 LZBase::blockSize() { return m_blockSize; } -void LZBase::setMinimumOffset(atUint32 minimumOffset) { m_minOffset = minimumOffset;} +void LZBase::setMinimumOffset(atUint32 minimumOffset) { m_minOffset = minimumOffset; } -atUint32 LZBase::minimumOffset() -{ - return m_minOffset; -} +atUint32 LZBase::minimumOffset() { return m_minOffset; } /* DerricMc: @@ -54,55 +39,51 @@ atUint32 LZBase::minimumOffset() and 17 bytes did match then 17 bytes match is return). */ -LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd) -{ - LZLengthOffset results = {0, 0}; - - //Returns negative 1 for Search failures since the current position is passed the size to be compressed - if (posPtr >= dataEnd) - { - results.length = -1; - return results; - } - - atUint8* searchWindow; - //LookAheadBuffer is ReadAheadBuffer Size if there are more bytes than ReadAheadBufferSize waiting - //to be compressed else the number of remaining bytes is the LookAheadBuffer - int lookAheadBuffer_len = ((int)(dataEnd - posPtr) < m_readAheadBuffer) ? (int)(dataEnd - posPtr) : m_readAheadBuffer; - int slidingBuffer = (int)(posPtr - dataBegin) - m_slidingWindow; - - if (slidingBuffer > 0) - searchWindow = dataBegin + slidingBuffer; - else - searchWindow = dataBegin; - - atUint8* endPos = posPtr + lookAheadBuffer_len; - - if (!((posPtr - dataBegin < 1) || (dataEnd - posPtr < m_minMatch))) - results = windowSearch(searchWindow, posPtr, endPos, posPtr - m_minOffset); +LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd) { + LZLengthOffset results = {0, 0}; + // Returns negative 1 for Search failures since the current position is passed the size to be compressed + if (posPtr >= dataEnd) { + results.length = -1; return results; + } + + atUint8* searchWindow; + // LookAheadBuffer is ReadAheadBuffer Size if there are more bytes than ReadAheadBufferSize waiting + // to be compressed else the number of remaining bytes is the LookAheadBuffer + int lookAheadBuffer_len = ((int)(dataEnd - posPtr) < m_readAheadBuffer) ? (int)(dataEnd - posPtr) : m_readAheadBuffer; + int slidingBuffer = (int)(posPtr - dataBegin) - m_slidingWindow; + + if (slidingBuffer > 0) + searchWindow = dataBegin + slidingBuffer; + else + searchWindow = dataBegin; + + atUint8* endPos = posPtr + lookAheadBuffer_len; + + if (!((posPtr - dataBegin < 1) || (dataEnd - posPtr < m_minMatch))) + results = windowSearch(searchWindow, posPtr, endPos, posPtr - m_minOffset); + + return results; } +// Returns the full length of string2 if they are equal else +// Return the number of characters that were equal before they weren't equal +int LZBase::subMatch(const uint8_t* str1, const uint8_t* str2, const int len) { + for (int i = 0; i < len; ++i) + if (str1[i] != str2[i]) + return i; -//Returns the full length of string2 if they are equal else -//Return the number of characters that were equal before they weren't equal -int LZBase::subMatch(const uint8_t* str1, const uint8_t* str2, const int len) -{ - for (int i = 0; i < len; ++i) - if (str1[i] != str2[i]) - return i; - - return len; + return len; } /* Normally a search for one byte is matched, then two, then three, all the way up to the size of the LookAheadBuffer. So I decided to skip the incremental search and search for the entire LookAheadBuffer and if the function doesn't find the bytes are - equal the function return the next best match(which means if the function look for 18 bytes and they are not found, return - the number of bytes that did match before it failed to match. The submatch is function returns the number of bytes that - were equal, which can result up to the bytes total length if both byte strings are equal. + equal the function return the next best match(which means if the function look for 18 bytes and they are not found, +return the number of bytes that did match before it failed to match. The submatch is function returns the number of +bytes that were equal, which can result up to the bytes total length if both byte strings are equal. ...[][][][][][][][][][][][]|[][][][][][][][][][][][][][] @@ -112,39 +93,35 @@ Normally a search for one byte is matched, then two, then three, all the way up Sliding Window Up to 4114 bytes */ -LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, atUint8* startLBPtr) -{ - atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); //Size of the entire sliding window - atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr); - LZLengthOffset result = {0, 0}; - atInt32 temp = 0; - - if (n > size) //If the string that is being looked for is bigger than the string that is being searched - return result; - - /*This makes sure that search for the searchPosPtr can be searched if an invalid position is given - An invalid position occurs if the amount of characters to search in_beginSearchPtr is less than the size - of searchPosPtr. In other words there has to be at least n characters left in the string - to have a chance to find n characters*/ - - do - { - temp = subMatch(startLBPtr, searchPosPtr, n); - - if (result.length < (atUint32)temp) - { - result.length = temp; - result.offset = (atInt32)(searchPosPtr - startLBPtr); - } - - if (result.length == (atUint32)n) - return result; - - //ReadAheadBuffer is the maximum size of a character match - - } - while ((startLBPtr--) > beginSearchPtr); +LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, + atUint8* startLBPtr) { + atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); // Size of the entire sliding window + atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr); + LZLengthOffset result = {0, 0}; + atInt32 temp = 0; + if (n > size) // If the string that is being looked for is bigger than the string that is being searched return result; -} + /*This makes sure that search for the searchPosPtr can be searched if an invalid position is given + An invalid position occurs if the amount of characters to search in_beginSearchPtr is less than the size + of searchPosPtr. In other words there has to be at least n characters left in the string + to have a chance to find n characters*/ + + do { + temp = subMatch(startLBPtr, searchPosPtr, n); + + if (result.length < (atUint32)temp) { + result.length = temp; + result.offset = (atInt32)(searchPosPtr - startLBPtr); + } + + if (result.length == (atUint32)n) + return result; + + // ReadAheadBuffer is the maximum size of a character match + + } while ((startLBPtr--) > beginSearchPtr); + + return result; +} diff --git a/src/LZ77/LZLookupTable.cpp b/src/LZ77/LZLookupTable.cpp index b1f5e2b..0809c84 100644 --- a/src/LZ77/LZLookupTable.cpp +++ b/src/LZ77/LZLookupTable.cpp @@ -1,129 +1,116 @@ #include "LZ77/LZLookupTable.hpp" #include -LZLookupTable::LZLookupTable() -{ +LZLookupTable::LZLookupTable() { + m_minimumMatch = 3; + m_slidingWindow = 4096; + m_lookAheadWindow = 18; + m_buffer.resize(m_minimumMatch); +} + +LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt32 lookAheadWindow) { + if (minimumMatch > 0) + m_minimumMatch = minimumMatch; + else m_minimumMatch = 3; + + if (slidingWindow > 0) + m_slidingWindow = slidingWindow; + else m_slidingWindow = 4096; + + if (lookAheadWindow > 0) + m_lookAheadWindow = lookAheadWindow; + else m_lookAheadWindow = 18; - m_buffer.resize(m_minimumMatch); + + m_buffer.reserve(m_minimumMatch); } -LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt32 lookAheadWindow) -{ - if (minimumMatch > 0) - m_minimumMatch = minimumMatch; - else - m_minimumMatch = 3; +LZLookupTable::~LZLookupTable() {} - if (slidingWindow > 0) - m_slidingWindow = slidingWindow; - else - m_slidingWindow = 4096; - - if (lookAheadWindow > 0) - m_lookAheadWindow = lookAheadWindow; - else - m_lookAheadWindow = 18; - - m_buffer.reserve(m_minimumMatch); +void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) { + if (lookAheadWindow > 0) + m_lookAheadWindow = lookAheadWindow; + else + m_lookAheadWindow = 18; } -LZLookupTable::~LZLookupTable() -{} +LZLengthOffset LZLookupTable::search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd) { + LZLengthOffset loPair = {0, 0}; -void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) -{ - if (lookAheadWindow > 0) - m_lookAheadWindow = lookAheadWindow; - else - m_lookAheadWindow = 18; -} - -LZLengthOffset LZLookupTable::search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd) -{ - LZLengthOffset loPair = {0, 0}; - - //Returns negative 1 for search failures since the current position is passed the size to be compressed - if (curPos >= dataEnd) - { - loPair.length = -1; - return loPair; - } - - std::copy(curPos, curPos + m_minimumMatch, m_buffer.begin()); - int32_t currentOffset = static_cast(curPos - dataBegin); - - //Find code - if (currentOffset > 0 && (dataEnd - curPos) >= m_minimumMatch) - { - auto elements = table.equal_range(m_buffer); - elements.second--; - elements.first--; - - //Iterate over keys in reverse order. C++11 guarantees that the relative order of elements is maintained for the same key - for (auto iter = elements.second; iter != elements.first; iter--) - { - int32_t matchLength = m_minimumMatch; - int32_t lookAheadBufferLength = ((dataEnd - curPos) < m_lookAheadWindow) ? static_cast(dataEnd - curPos) : m_lookAheadWindow; - - for (; matchLength < lookAheadBufferLength; ++matchLength) - { - if (*(dataBegin + iter->second + matchLength) != *(curPos + matchLength)) - break; - } - - //Store the longest match found so far into length_offset struct. - //When lengths are the same the closer offset to the lookahead buffer wins - if (loPair.length < (atUint32)matchLength) - { - loPair.length = matchLength; - loPair.offset = currentOffset - iter->second; - } - - //Found the longest match so break out of loop - if (loPair.length == (atUint32)m_lookAheadWindow) - break; - } - } - - //end find code - //Insert code - table.insert(std::make_pair(m_buffer, currentOffset)); - - for (atUint32 i = 1; i < loPair.length; i++) - { - if (dataEnd - (curPos + i) < m_minimumMatch) - break; - - std::copy(curPos + i, curPos + m_minimumMatch + i, m_buffer.begin()); - table.insert(std::make_pair(m_buffer, currentOffset + i)); - - } - - //end insert code - //Delete code - int32_t slidingWindowOffset = std::max(0, currentOffset - m_slidingWindow);//Absolute offset - int32_t tablesize = static_cast(table.size()); - - for (int32_t i = 0; i < tablesize - m_slidingWindow; ++i) - { - std::copy(dataBegin + slidingWindowOffset + i, dataBegin + slidingWindowOffset + m_minimumMatch + i, m_buffer.begin()); - auto elements = table.equal_range(m_buffer); - - for (auto iter = elements.first; iter != elements.second; iter++) - { - if (slidingWindowOffset + i == iter->second) - { - table.erase(iter); - //There should no occurance of the map with the same value - break; - } - } - } - - //end delete code + // Returns negative 1 for search failures since the current position is passed the size to be compressed + if (curPos >= dataEnd) { + loPair.length = -1; return loPair; - //break lookupTable.cpp:109 if table.size()> 4096 + } + std::copy(curPos, curPos + m_minimumMatch, m_buffer.begin()); + int32_t currentOffset = static_cast(curPos - dataBegin); + + // Find code + if (currentOffset > 0 && (dataEnd - curPos) >= m_minimumMatch) { + auto elements = table.equal_range(m_buffer); + elements.second--; + elements.first--; + + // Iterate over keys in reverse order. C++11 guarantees that the relative order of elements is maintained for the + // same key + for (auto iter = elements.second; iter != elements.first; iter--) { + int32_t matchLength = m_minimumMatch; + int32_t lookAheadBufferLength = + ((dataEnd - curPos) < m_lookAheadWindow) ? static_cast(dataEnd - curPos) : m_lookAheadWindow; + + for (; matchLength < lookAheadBufferLength; ++matchLength) { + if (*(dataBegin + iter->second + matchLength) != *(curPos + matchLength)) + break; + } + + // Store the longest match found so far into length_offset struct. + // When lengths are the same the closer offset to the lookahead buffer wins + if (loPair.length < (atUint32)matchLength) { + loPair.length = matchLength; + loPair.offset = currentOffset - iter->second; + } + + // Found the longest match so break out of loop + if (loPair.length == (atUint32)m_lookAheadWindow) + break; + } + } + + // end find code + // Insert code + table.insert(std::make_pair(m_buffer, currentOffset)); + + for (atUint32 i = 1; i < loPair.length; i++) { + if (dataEnd - (curPos + i) < m_minimumMatch) + break; + + std::copy(curPos + i, curPos + m_minimumMatch + i, m_buffer.begin()); + table.insert(std::make_pair(m_buffer, currentOffset + i)); + } + + // end insert code + // Delete code + int32_t slidingWindowOffset = std::max(0, currentOffset - m_slidingWindow); // Absolute offset + int32_t tablesize = static_cast(table.size()); + + for (int32_t i = 0; i < tablesize - m_slidingWindow; ++i) { + std::copy(dataBegin + slidingWindowOffset + i, dataBegin + slidingWindowOffset + m_minimumMatch + i, + m_buffer.begin()); + auto elements = table.equal_range(m_buffer); + + for (auto iter = elements.first; iter != elements.second; iter++) { + if (slidingWindowOffset + i == iter->second) { + table.erase(iter); + // There should no occurance of the map with the same value + break; + } + } + } + + // end delete code + return loPair; + // break lookupTable.cpp:109 if table.size()> 4096 } diff --git a/src/LZ77/LZType10.cpp b/src/LZ77/LZType10.cpp index b3c59f5..ee033a9 100644 --- a/src/LZ77/LZType10.cpp +++ b/src/LZ77/LZType10.cpp @@ -4,140 +4,125 @@ #include LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize) - : LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) -{ - //ReadAheadBuffer is normalize between (minumum match) and(minimum match + 15) so that matches fit within - //4-bits. - m_readAheadBuffer = m_minMatch + 0xF; +: LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) { + // ReadAheadBuffer is normalize between (minumum match) and(minimum match + 15) so that matches fit within + // 4-bits. + m_readAheadBuffer = m_minMatch + 0xF; } -atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLength) -{ - atUint32 encodeSize = (srcLength << 8) | (0x10); - encodeSize = athena::utility::LittleUint32(encodeSize); //File size needs to be written as little endian always +atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLength) { + atUint32 encodeSize = (srcLength << 8) | (0x10); + encodeSize = athena::utility::LittleUint32(encodeSize); // File size needs to be written as little endian always - athena::io::MemoryCopyWriter outbuf("tmp"); - outbuf.writeUint32(encodeSize); + athena::io::MemoryCopyWriter outbuf("tmp"); + outbuf.writeUint32(encodeSize); - atUint8* ptrStart = (atUint8*)src; - atUint8* ptrEnd = (atUint8*)(src + srcLength); + atUint8* ptrStart = (atUint8*)src; + atUint8* ptrEnd = (atUint8*)(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 + // 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 - 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; + 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; - for (atInt32 i = 0; i < m_blockSize; i++) - { - //length_offset searchResult=Search(ptrStart, filedata, ptrEnd); - LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); + for (atInt32 i = 0; i < m_blockSize; i++) { + // length_offset searchResult=Search(ptrStart, filedata, ptrEnd); + 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) - { - //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); + // If the number of bytes to be compressed is at least the size of the Minimum match + if (searchResult.length >= (atUint32)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); - memcpy(ptrBytes, &lenOff, sizeof(atUint16)); + memcpy(ptrBytes, &lenOff, sizeof(atUint16)); - ptrBytes += sizeof(atUint16); + ptrBytes += sizeof(atUint16); - ptrStart += searchResult.length; - - blockLen |= (1 << (7 - i)); - //Stores which of the next 8 bytes is compressed - //bit 1 for compress and bit 0 for not compressed - } - else - *ptrBytes++ = *ptrStart++; - } - - outbuf.writeByte(blockLen); - outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + ptrStart += searchResult.length; + blockLen |= (1 << (7 - i)); + // Stores which of the next 8 bytes is compressed + // bit 1 for compress and bit 0 for not compressed + } else + *ptrBytes++ = *ptrStart++; } - delete[] compressedBytes; - compressedBytes = nullptr; + outbuf.writeByte(blockLen); + outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + } - //Add zeros until the file is a multiple of 4 - while ((outbuf.position() % 4) != 0) - outbuf.writeByte(0); + delete[] compressedBytes; + compressedBytes = nullptr; - *dstBuf = outbuf.data(); - outbuf.save(); - return (atUint32)outbuf.length(); + // Add zeros until the file is a multiple of 4 + while ((outbuf.position() % 4) != 0) + outbuf.writeByte(0); + + *dstBuf = outbuf.data(); + outbuf.save(); + return (atUint32)outbuf.length(); } -atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) -{ - if (*(atUint8*)(src) != 0x10) - return 0; +atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) { + if (*(atUint8*)(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 + 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 - atUint8* uncompressedData = new atUint8[uncompressedSize]; - atUint8* outputPtr = uncompressedData; - atUint8* outputEndPtr = uncompressedData + uncompressedSize; - atUint8* inputPtr = (atUint8*)src + 4; - atUint8* inputEndPtr = (atUint8*)src + srcLength; + atUint8* uncompressedData = new atUint8[uncompressedSize]; + atUint8* outputPtr = uncompressedData; + atUint8* outputEndPtr = uncompressedData + uncompressedSize; + atUint8* inputPtr = (atUint8*)src + 4; + atUint8* inputEndPtr = (atUint8*)src + srcLength; - while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) - { + while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) { - atUint8 isCompressed = *inputPtr++; - - for (atUint32 i = 0; i < (atUint32)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) - { - atUint16 lenOff; - memcpy(&lenOff, inputPtr, sizeof(atUint16)); - athena::utility::BigUint16(lenOff); - inputPtr += sizeof(atUint16); //Move forward two bytes - //length offset pair has been decoded. - LZLengthOffset decoding; - decoding.length = (lenOff >> 12) + m_minMatch; - decoding.offset = static_cast((lenOff & 0xFFF) + 1); - - - 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; - uncompressedData = nullptr; - dst = nullptr; - return 0; - } - - for (atUint32 j = 0; j < decoding.length; ++j) - outputPtr[j] = (outputPtr - decoding.offset)[j]; - - outputPtr += decoding.length; - } - else - *outputPtr++ = *inputPtr++; - - if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) - break; + atUint8 isCompressed = *inputPtr++; + for (atUint32 i = 0; i < (atUint32)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) { + atUint16 lenOff; + memcpy(&lenOff, inputPtr, sizeof(atUint16)); + athena::utility::BigUint16(lenOff); + inputPtr += sizeof(atUint16); // Move forward two bytes + // length offset pair has been decoded. + LZLengthOffset decoding; + decoding.length = (lenOff >> 12) + m_minMatch; + decoding.offset = static_cast((lenOff & 0xFFF) + 1); + 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; + uncompressedData = nullptr; + dst = nullptr; + return 0; } + + for (atUint32 j = 0; j < decoding.length; ++j) + outputPtr[j] = (outputPtr - decoding.offset)[j]; + + outputPtr += decoding.length; + } else + *outputPtr++ = *inputPtr++; + + if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) + break; } + } - *dst = uncompressedData; + *dst = uncompressedData; - return uncompressedSize; + return uncompressedSize; } - diff --git a/src/LZ77/LZType11.cpp b/src/LZ77/LZType11.cpp index 774a056..41cee43 100644 --- a/src/LZ77/LZType11.cpp +++ b/src/LZ77/LZType11.cpp @@ -3,233 +3,209 @@ #include #include - LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) - : LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) -{ - m_readAheadBuffer = (0xF + 0xFF + 0xFFFF + m_minMatch); - m_lookupTable.setLookAheadWindow(m_readAheadBuffer); +: LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) { + m_readAheadBuffer = (0xF + 0xFF + 0xFFFF + m_minMatch); + m_lookupTable.setLookAheadWindow(m_readAheadBuffer); } -atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) -{ - athena::io::MemoryCopyWriter outbuff("tmp"); +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 - { - atUint32 encodeFlag = 0x11; - athena::utility::LittleUint32(encodeFlag); - athena::utility::LittleUint32(srcLength);//Filesize data is little endian - outbuff.writeUint32(encodeFlag); - outbuff.writeUint32(srcLength); + 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); - } + } else { + atUint32 encodeSize = (srcLength << 8) | (0x11); + athena::utility::LittleUint32(encodeSize); + outbuff.writeUint32(encodeSize); + } - atUint8* ptrStart = (atUint8*)src; - atUint8* ptrEnd = (atUint8*)(src + srcLength); + atUint8* ptrStart = (atUint8*)src; + atUint8* ptrEnd = (atUint8*)(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 + // 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; + 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; - /* - Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15. - 17 gets mapped to 1 and 272 gets mapped to 255 - 273 gets mapped to 0 and 65808 gets mapped to 65535 + /* + Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15. + 17 gets mapped to 1 and 272 gets mapped to 255 + 273 gets mapped to 0 and 65808 gets mapped to 65535 - A two byte match uses 4 bits - A three byte match uses 8 bits - A four byte match uses 16 bits - In each case the offset uses 12 bits - In the two byte case the length is normalized so that the first 4 bits are numbers between between 2 and 15 - In the three byte case the first 4 bits are 0000 - In the four byte case the first 4 bits a 0001 - */ - while (ptrStart < ptrEnd) - { - 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; + A two byte match uses 4 bits + A three byte match uses 8 bits + A four byte match uses 16 bits + In each case the offset uses 12 bits + In the two byte case the length is normalized so that the first 4 bits are numbers between between 2 and 15 + In the three byte case the first 4 bits are 0000 + In the four byte case the first 4 bits a 0001 + */ + while (ptrStart < ptrEnd) { + 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; - for (atInt32 i = 0; i < m_blockSize; i++) - { - //length_offset searchResult=Search(filedata,ptrStart,ptrEnd); - LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); + for (atInt32 i = 0; i < m_blockSize; i++) { + // length_offset searchResult=Search(filedata,ptrStart,ptrEnd); + 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) - { - //Gotta swap the bytes since system is wii is big endian and most computers are little endian - - if (searchResult.length <= maxTwoByteMatch) - { - atUint16 lenOff = ((((searchResult.length - 1) & 0xF) << 12) | //Bits 15-12 - ((searchResult.offset - 1) & 0xFFF) //Bits 11-0 - ); - athena::utility::BigUint16(lenOff); - memcpy(ptrBytes, &lenOff, 2); - ptrBytes += 2; - } - else if (searchResult.length <= maxThreeByteMatch) - { - atUint32 lenOff = ((((searchResult.length - minThreeByteMatch) & 0xFF) << 12) | //Bits 20-12 - ((searchResult.offset - 1) & 0xFFF) //Bits 11-0 - ); - athena::utility::BigUint32(lenOff); - memcpy(ptrBytes, (atUint8*)&lenOff + 1, 3); //Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456 - ptrBytes += 3; - } - else if (searchResult.length <= (atUint32)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 - ); - athena::utility::BigUint32(lenOff); - memcpy(ptrBytes, &lenOff, 4); - ptrBytes += 4; - } - - ptrStart += searchResult.length; - - blockSize |= (1 << (7 - i)); - //Stores which of the next 8 bytes is compressed - //bit 1 for compress and bit 0 for not compressed - } - else - *ptrBytes++ = *ptrStart++; + // If the number of bytes to be compressed is at least the size of the Minimum match + if (searchResult.length >= (atUint32)m_minMatch) { + // Gotta swap the bytes since system is wii is big endian and most computers are little endian + if (searchResult.length <= maxTwoByteMatch) { + atUint16 lenOff = ((((searchResult.length - 1) & 0xF) << 12) | // Bits 15-12 + ((searchResult.offset - 1) & 0xFFF) // Bits 11-0 + ); + athena::utility::BigUint16(lenOff); + memcpy(ptrBytes, &lenOff, 2); + ptrBytes += 2; + } else if (searchResult.length <= maxThreeByteMatch) { + atUint32 lenOff = ((((searchResult.length - minThreeByteMatch) & 0xFF) << 12) | // Bits 20-12 + ((searchResult.offset - 1) & 0xFFF) // Bits 11-0 + ); + athena::utility::BigUint32(lenOff); + memcpy(ptrBytes, (atUint8*)&lenOff + 1, + 3); // Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456 + ptrBytes += 3; + } else if (searchResult.length <= (atUint32)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 + ); + athena::utility::BigUint32(lenOff); + memcpy(ptrBytes, &lenOff, 4); + ptrBytes += 4; } - outbuff.writeByte(blockSize); - outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + ptrStart += searchResult.length; + blockSize |= (1 << (7 - i)); + // Stores which of the next 8 bytes is compressed + // bit 1 for compress and bit 0 for not compressed + } else + *ptrBytes++ = *ptrStart++; } - delete []compressedBytes; - compressedBytes = NULL; + outbuff.writeByte(blockSize); + outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + } - //Add zeros until the file is a multiple of 4 - while ((outbuff.position() % 4) != 0) - outbuff.writeByte(0); + delete[] compressedBytes; + compressedBytes = NULL; - *dst = outbuff.data(); - return (atUint32)outbuff.length(); + // Add zeros until the file is a multiple of 4 + while ((outbuff.position() % 4) != 0) + outbuff.writeByte(0); + + *dst = outbuff.data(); + return (atUint32)outbuff.length(); } -atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) -{ - if (*(atUint8*)(src) != 0x11) - return 0; +atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) { + if (*(atUint8*)(src) != 0x11) + return 0; - atUint32 uncompressedLen = *(atUint32*)(src); - 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; + atUint32 uncompressedLen = *(atUint32*)(src); + 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); - filesize = athena::utility::LittleUint32(filesize); - 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); + 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; + atUint8* uncompressedData = new atUint8[uncompressedLen]; + atUint8* outputPtr = uncompressedData; + atUint8* outputEndPtr = uncompressedData + uncompressedLen; + atUint8* inputPtr = (atUint8*)src + currentOffset; + atUint8* inputEndPtr = (atUint8*)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; + 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; - while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) - { + while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) { - atUint8 isCompressed = *inputPtr++; + atUint8 isCompressed = *inputPtr++; - for (atInt32 i = 0; i < m_blockSize; i++) + 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 + + if (metaDataSize >= 2) // Two Bytes of Length/Offset MetaData { - //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 - - 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 - { - atUint32 lenOff = 0; - memcpy((atUint8*)&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 - { - atUint32 lenOff = 0; - memcpy(&lenOff, inputPtr, 4); - inputPtr += 4; - athena::utility::BigUint32(lenOff); - - 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; - return 0; - } - - for (atUint32 j = 0; j < decoding.length; ++j) - outputPtr[j] = (outputPtr - decoding.offset)[j]; - - outputPtr += decoding.length; - } - else - *outputPtr++ = *inputPtr++; - - if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) - break; - + 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 + { + atUint32 lenOff = 0; + memcpy((atUint8*)&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 + { + atUint32 lenOff = 0; + memcpy(&lenOff, inputPtr, 4); + inputPtr += 4; + athena::utility::BigUint32(lenOff); + 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; + return 0; + } + + for (atUint32 j = 0; j < decoding.length; ++j) + outputPtr[j] = (outputPtr - decoding.offset)[j]; + + outputPtr += decoding.length; + } else + *outputPtr++ = *inputPtr++; + + if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) + break; } + } - *dst = uncompressedData; - return uncompressedLen; + *dst = uncompressedData; + return uncompressedLen; } - diff --git a/src/aes.cpp b/src/aes.cpp index 3abc4dc..e70caad 100644 --- a/src/aes.cpp +++ b/src/aes.cpp @@ -11,608 +11,563 @@ #define _AES_NI 1 #endif -namespace athena -{ +namespace athena { /* rotates x one bit to the left */ -#define ROTL(x) (((x)>>7)|((x)<<1)) +#define ROTL(x) (((x) >> 7) | ((x) << 1)) /* Rotates 32-bit word left by 1, 2 or 3 byte */ -#define ROTL8(x) (((x)<<8)|((x)>>24)) -#define ROTL16(x) (((x)<<16)|((x)>>16)) -#define ROTL24(x) (((x)<<24)|((x)>>8)) +#define ROTL8(x) (((x) << 8) | ((x) >> 24)) +#define ROTL16(x) (((x) << 16) | ((x) >> 16)) +#define ROTL24(x) (((x) << 24) | ((x) >> 8)) static const uint8_t InCo[4] = {0xB, 0xD, 0x9, 0xE}; /* Inverse Coefficients */ -static inline uint32_t pack(const uint8_t* b) -{ - /* pack bytes into a 32-bit Word */ - return ((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0]; +static inline uint32_t pack(const uint8_t* b) { + /* pack bytes into a 32-bit Word */ + return ((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0]; } -static inline void unpack(uint32_t a, uint8_t* b) -{ - /* unpack bytes from a word */ - b[0] = (uint8_t)a; - b[1] = (uint8_t)(a >> 8); - b[2] = (uint8_t)(a >> 16); - b[3] = (uint8_t)(a >> 24); +static inline void unpack(uint32_t a, uint8_t* b) { + /* unpack bytes from a word */ + b[0] = (uint8_t)a; + b[1] = (uint8_t)(a >> 8); + b[2] = (uint8_t)(a >> 16); + b[3] = (uint8_t)(a >> 24); } -static inline uint8_t xtime(uint8_t a) -{ - return ((a << 1) ^ (((a>>7) & 1) * 0x11B)); -} +static inline uint8_t xtime(uint8_t a) { return ((a << 1) ^ (((a >> 7) & 1) * 0x11B)); } -static const struct SoftwareAESTables -{ - uint8_t fbsub[256]; - uint8_t rbsub[256]; - uint8_t ptab[256], ltab[256]; - uint32_t ftable[256]; - uint32_t rtable[256]; - uint32_t rco[30]; +static const struct SoftwareAESTables { + uint8_t fbsub[256]; + uint8_t rbsub[256]; + uint8_t ptab[256], ltab[256]; + uint32_t ftable[256]; + uint32_t rtable[256]; + uint32_t rco[30]; - uint8_t bmul(uint8_t x, uint8_t y) const - { - /* x.y= AntiLog(Log(x) + Log(y)) */ - if (x && y) return ptab[(ltab[x] + ltab[y]) % 255]; - else return 0; + uint8_t bmul(uint8_t x, uint8_t y) const { + /* x.y= AntiLog(Log(x) + Log(y)) */ + if (x && y) + return ptab[(ltab[x] + ltab[y]) % 255]; + else + return 0; + } + + uint32_t SubByte(uint32_t a) const { + uint8_t b[4]; + unpack(a, b); + b[0] = fbsub[b[0]]; + b[1] = fbsub[b[1]]; + b[2] = fbsub[b[2]]; + b[3] = fbsub[b[3]]; + return pack(b); + } + + uint8_t product(uint32_t x, uint32_t y) const { + /* dot product of two 4-byte arrays */ + uint8_t xb[4], yb[4]; + unpack(x, xb); + unpack(y, yb); + return bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2], yb[2]) ^ bmul(xb[3], yb[3]); + } + + uint32_t InvMixCol(uint32_t x) const { + /* matrix Multiplication */ + uint32_t y, m; + uint8_t b[4]; + + m = pack(InCo); + b[3] = product(m, x); + m = ROTL24(m); + b[2] = product(m, x); + m = ROTL24(m); + b[1] = product(m, x); + m = ROTL24(m); + b[0] = product(m, x); + y = pack(b); + return y; + } + + uint8_t ByteSub(uint8_t x) const { + uint8_t y = ptab[255 - ltab[x]]; /* multiplicative inverse */ + x = y; + x = ROTL(x); + y ^= x; + x = ROTL(x); + y ^= x; + x = ROTL(x); + y ^= x; + x = ROTL(x); + y ^= x; + y ^= 0x63; + return y; + } + + SoftwareAESTables() { + /* generate tables */ + int i; + uint8_t y, b[4]; + + /* use 3 as primitive root to generate power and log tables */ + + ltab[0] = 0; + ptab[0] = 1; + ltab[1] = 0; + ptab[1] = 3; + ltab[3] = 1; + + for (i = 2; i < 256; i++) { + ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]); + ltab[ptab[i]] = i; } - uint32_t SubByte(uint32_t a) const - { - uint8_t b[4]; - unpack(a, b); - b[0] = fbsub[b[0]]; - b[1] = fbsub[b[1]]; - b[2] = fbsub[b[2]]; - b[3] = fbsub[b[3]]; - return pack(b); + /* affine transformation:- each bit is xored with itself shifted one bit */ + + fbsub[0] = 0x63; + rbsub[0x63] = 0; + + for (i = 1; i < 256; i++) { + y = ByteSub((uint8_t)i); + fbsub[i] = y; + rbsub[y] = i; } - uint8_t product(uint32_t x, uint32_t y) const - { - /* dot product of two 4-byte arrays */ - uint8_t xb[4], yb[4]; - unpack(x, xb); - unpack(y, yb); - return bmul(xb[0], yb[0])^bmul(xb[1], yb[1])^bmul(xb[2], yb[2])^bmul(xb[3], yb[3]); + for (i = 0, y = 1; i < 30; i++) { + rco[i] = y; + y = xtime(y); } - uint32_t InvMixCol(uint32_t x) const - { - /* matrix Multiplication */ - uint32_t y, m; - uint8_t b[4]; + /* calculate forward and reverse tables */ + for (i = 0; i < 256; i++) { + y = fbsub[i]; + b[3] = y ^ xtime(y); + b[2] = y; + b[1] = y; + b[0] = xtime(y); + ftable[i] = pack(b); - m = pack(InCo); - b[3] = product(m, x); - m = ROTL24(m); - b[2] = product(m, x); - m = ROTL24(m); - b[1] = product(m, x); - m = ROTL24(m); - b[0] = product(m, x); - y = pack(b); - return y; - } - - uint8_t ByteSub(uint8_t x) const - { - uint8_t y = ptab[255 - ltab[x]]; /* multiplicative inverse */ - x = y; - x = ROTL(x); - y ^= x; - x = ROTL(x); - y ^= x; - x = ROTL(x); - y ^= x; - x = ROTL(x); - y ^= x; - y ^= 0x63; - return y; - } - - SoftwareAESTables() - { - /* generate tables */ - int i; - uint8_t y, b[4]; - - /* use 3 as primitive root to generate power and log tables */ - - ltab[0] = 0; - ptab[0] = 1; - ltab[1] = 0; - ptab[1] = 3; - ltab[3] = 1; - - for (i = 2; i < 256; i++) - { - ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]); - ltab[ptab[i]] = i; - } - - /* affine transformation:- each bit is xored with itself shifted one bit */ - - fbsub[0] = 0x63; - rbsub[0x63] = 0; - - for (i = 1; i < 256; i++) - { - y = ByteSub((uint8_t)i); - fbsub[i] = y; - rbsub[y] = i; - } - - for (i = 0, y = 1; i < 30; i++) - { - rco[i] = y; - y = xtime(y); - } - - /* calculate forward and reverse tables */ - for (i = 0; i < 256; i++) - { - y = fbsub[i]; - b[3] = y ^ xtime(y); - b[2] = y; - b[1] = y; - b[0] = xtime(y); - ftable[i] = pack(b); - - y = rbsub[i]; - b[3] = bmul(InCo[0], y); - b[2] = bmul(InCo[1], y); - b[1] = bmul(InCo[2], y); - b[0] = bmul(InCo[3], y); - rtable[i] = pack(b); - } + y = rbsub[i]; + b[3] = bmul(InCo[0], y); + b[2] = bmul(InCo[1], y); + b[1] = bmul(InCo[2], y); + b[0] = bmul(InCo[3], y); + rtable[i] = pack(b); } + } } AEStb; -class SoftwareAES : public IAES -{ +class SoftwareAES : public IAES { protected: - /* Parameter-dependent data */ - int Nk, Nb, Nr; - uint8_t fi[24], ri[24]; - uint32_t fkey[120]; - uint32_t rkey[120]; + /* Parameter-dependent data */ + int Nk, Nb, Nr; + uint8_t fi[24], ri[24]; + uint32_t fkey[120]; + uint32_t rkey[120]; - void gkey(int nb, int nk, const uint8_t* key); - void _encrypt(uint8_t* buff); - void _decrypt(uint8_t* buff); + void gkey(int nb, int nk, const uint8_t* key); + void _encrypt(uint8_t* buff); + void _decrypt(uint8_t* buff); public: - void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len); - void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len); - void setKey(const uint8_t* key); + void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len); + void decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len); + void setKey(const uint8_t* key); }; -void SoftwareAES::gkey(int nb, int nk, const uint8_t* key) -{ - /* blocksize=32*nb bits. Key=32*nk bits */ - /* currently nb,bk = 4, 6 or 8 */ - /* key comes as 4*Nk bytes */ - /* Key Scheduler. Create expanded encryption key */ - int i, j, k, m, N; - int C1, C2, C3; - uint32_t CipherKey[8]; +void SoftwareAES::gkey(int nb, int nk, const uint8_t* key) { + /* blocksize=32*nb bits. Key=32*nk bits */ + /* currently nb,bk = 4, 6 or 8 */ + /* key comes as 4*Nk bytes */ + /* Key Scheduler. Create expanded encryption key */ + int i, j, k, m, N; + int C1, C2, C3; + uint32_t CipherKey[8]; - Nb = nb; - Nk = nk; + Nb = nb; + Nk = nk; - /* Nr is number of rounds */ - if (Nb >= Nk) Nr = 6 + Nb; - else Nr = 6 + Nk; + /* Nr is number of rounds */ + if (Nb >= Nk) + Nr = 6 + Nb; + else + Nr = 6 + Nk; - C1 = 1; + C1 = 1; - if (Nb < 8) { C2 = 2; C3 = 3; } - else { C2 = 3; C3 = 4; } + if (Nb < 8) { + C2 = 2; + C3 = 3; + } else { + C2 = 3; + C3 = 4; + } - /* pre-calculate forward and reverse increments */ - for (m = j = 0; j < nb; j++, m += 3) - { - fi[m] = (j + C1) % nb; - fi[m + 1] = (j + C2) % nb; - fi[m + 2] = (j + C3) % nb; - ri[m] = (nb + j - C1) % nb; - ri[m + 1] = (nb + j - C2) % nb; - ri[m + 2] = (nb + j - C3) % nb; + /* pre-calculate forward and reverse increments */ + for (m = j = 0; j < nb; j++, m += 3) { + fi[m] = (j + C1) % nb; + fi[m + 1] = (j + C2) % nb; + fi[m + 2] = (j + C3) % nb; + ri[m] = (nb + j - C1) % nb; + ri[m + 1] = (nb + j - C2) % nb; + ri[m + 2] = (nb + j - C3) % nb; + } + + N = Nb * (Nr + 1); + + for (i = j = 0; i < Nk; i++, j += 4) { + CipherKey[i] = pack(key + j); + } + + for (i = 0; i < Nk; i++) + fkey[i] = CipherKey[i]; + + for (j = Nk, k = 0; j < N; j += Nk, k++) { + fkey[j] = fkey[j - Nk] ^ AEStb.SubByte(ROTL24(fkey[j - 1])) ^ AEStb.rco[k]; + + if (Nk <= 6) { + for (i = 1; i < Nk && (i + j) < N; i++) + fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; + } else { + for (i = 1; i < 4 && (i + j) < N; i++) + fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; + + if ((j + 4) < N) + fkey[j + 4] = fkey[j + 4 - Nk] ^ AEStb.SubByte(fkey[j + 3]); + + for (i = 5; i < Nk && (i + j) < N; i++) + fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; } + } - N = Nb * (Nr + 1); + /* now for the expanded decrypt key in reverse order */ - for (i = j = 0; i < Nk; i++, j += 4) - { - CipherKey[i] = pack(key + j); - } + for (j = 0; j < Nb; j++) + rkey[j + N - Nb] = fkey[j]; - for (i = 0; i < Nk; i++) fkey[i] = CipherKey[i]; + for (i = Nb; i < N - Nb; i += Nb) { + k = N - Nb - i; - for (j = Nk, k = 0; j < N; j += Nk, k++) - { - fkey[j] = fkey[j - Nk] ^ AEStb.SubByte(ROTL24(fkey[j - 1]))^AEStb.rco[k]; + for (j = 0; j < Nb; j++) + rkey[k + j] = AEStb.InvMixCol(fkey[i + j]); + } - if (Nk <= 6) - { - for (i = 1; i < Nk && (i + j) < N; i++) - fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; - } - else - { - for (i = 1; i < 4 && (i + j) < N; i++) - fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; - - if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ AEStb.SubByte(fkey[j + 3]); - - for (i = 5; i < Nk && (i + j) < N; i++) - fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; - } - - } - - /* now for the expanded decrypt key in reverse order */ - - for (j = 0; j < Nb; j++) rkey[j + N - Nb] = fkey[j]; - - for (i = Nb; i < N - Nb; i += Nb) - { - k = N - Nb - i; - - for (j = 0; j < Nb; j++) rkey[k + j] = AEStb.InvMixCol(fkey[i + j]); - } - - for (j = N - Nb; j < N; j++) rkey[j - N + Nb] = fkey[j]; + for (j = N - Nb; j < N; j++) + rkey[j - N + Nb] = fkey[j]; } - /* There is an obvious time/space trade-off possible here. * * Instead of just one ftable[], I could have 4, the other * * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */ -void SoftwareAES::_encrypt(uint8_t* buff) -{ - int i, j, k, m; - uint32_t a[8], b[8], *x, *y, *t; +void SoftwareAES::_encrypt(uint8_t* buff) { + int i, j, k, m; + uint32_t a[8], b[8], *x, *y, *t; - for (i = j = 0; i < Nb; i++, j += 4) - { - a[i] = pack(buff + j); - a[i] ^= fkey[i]; + for (i = j = 0; i < Nb; i++, j += 4) { + a[i] = pack(buff + j); + a[i] ^= fkey[i]; + } + + k = Nb; + x = a; + y = b; + + /* State alternates between a and b */ + for (i = 1; i < Nr; i++) { + /* Nr is number of rounds. May be odd. */ + + /* if Nb is fixed - unroll this next + loop and hard-code in the values of fi[] */ + + for (m = j = 0; j < Nb; j++, m += 3) { + /* deal with each 32-bit element of the State */ + /* This is the time-critical bit */ + y[j] = fkey[k++] ^ AEStb.ftable[(uint8_t)x[j]] ^ ROTL8(AEStb.ftable[(uint8_t)(x[fi[m]] >> 8)]) ^ + ROTL16(AEStb.ftable[(uint8_t)(x[fi[m + 1]] >> 16)]) ^ ROTL24(AEStb.ftable[(uint8_t)(x[fi[m + 2]] >> 24)]); } - k = Nb; - x = a; - y = b; + t = x; + x = y; + y = t; /* swap pointers */ + } - /* State alternates between a and b */ - for (i = 1; i < Nr; i++) - { - /* Nr is number of rounds. May be odd. */ + /* Last Round - unroll if possible */ + for (m = j = 0; j < Nb; j++, m += 3) { + y[j] = fkey[k++] ^ (uint32_t)AEStb.fbsub[(uint8_t)x[j]] ^ ROTL8((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m]] >> 8)]) ^ + ROTL16((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 1]] >> 16)]) ^ + ROTL24((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 2]] >> 24)]); + } - /* if Nb is fixed - unroll this next - loop and hard-code in the values of fi[] */ + for (i = j = 0; i < Nb; i++, j += 4) { + unpack(y[i], (uint8_t*)&buff[j]); + x[i] = y[i] = 0; /* clean up stack */ + } - for (m = j = 0; j < Nb; j++, m += 3) - { - /* deal with each 32-bit element of the State */ - /* This is the time-critical bit */ - y[j] = fkey[k++] ^ AEStb.ftable[(uint8_t)x[j]] ^ - ROTL8(AEStb.ftable[(uint8_t)(x[fi[m]] >> 8)])^ - ROTL16(AEStb.ftable[(uint8_t)(x[fi[m + 1]] >> 16)])^ - ROTL24(AEStb.ftable[(uint8_t)(x[fi[m + 2]] >> 24)]); - } - - t = x; - x = y; - y = t; /* swap pointers */ - } - - /* Last Round - unroll if possible */ - for (m = j = 0; j < Nb; j++, m += 3) - { - y[j] = fkey[k++] ^ (uint32_t)AEStb.fbsub[(uint8_t)x[j]] ^ - ROTL8((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m]] >> 8)])^ - ROTL16((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 1]] >> 16)])^ - ROTL24((uint32_t)AEStb.fbsub[(uint8_t)(x[fi[m + 2]] >> 24)]); - } - - for (i = j = 0; i < Nb; i++, j += 4) - { - unpack(y[i], (uint8_t*)&buff[j]); - x[i] = y[i] = 0; /* clean up stack */ - } - - return; + return; } -void SoftwareAES::_decrypt(uint8_t* buff) -{ - int i, j, k, m; - uint32_t a[8], b[8], *x, *y, *t; +void SoftwareAES::_decrypt(uint8_t* buff) { + int i, j, k, m; + uint32_t a[8], b[8], *x, *y, *t; - for (i = j = 0; i < Nb; i++, j += 4) - { - a[i] = pack(buff + j); - a[i] ^= rkey[i]; + for (i = j = 0; i < Nb; i++, j += 4) { + a[i] = pack(buff + j); + a[i] ^= rkey[i]; + } + + k = Nb; + x = a; + y = b; + + /* State alternates between a and b */ + for (i = 1; i < Nr; i++) { + /* Nr is number of rounds. May be odd. */ + + /* if Nb is fixed - unroll this next + loop and hard-code in the values of ri[] */ + + for (m = j = 0; j < Nb; j++, m += 3) { + /* This is the time-critical bit */ + y[j] = rkey[k++] ^ AEStb.rtable[(uint8_t)x[j]] ^ ROTL8(AEStb.rtable[(uint8_t)(x[ri[m]] >> 8)]) ^ + ROTL16(AEStb.rtable[(uint8_t)(x[ri[m + 1]] >> 16)]) ^ ROTL24(AEStb.rtable[(uint8_t)(x[ri[m + 2]] >> 24)]); } - k = Nb; - x = a; - y = b; + t = x; + x = y; + y = t; /* swap pointers */ + } - /* State alternates between a and b */ - for (i = 1; i < Nr; i++) - { - /* Nr is number of rounds. May be odd. */ + /* Last Round - unroll if possible */ + for (m = j = 0; j < Nb; j++, m += 3) { + y[j] = rkey[k++] ^ (uint32_t)AEStb.rbsub[(uint8_t)x[j]] ^ ROTL8((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m]] >> 8)]) ^ + ROTL16((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 1]] >> 16)]) ^ + ROTL24((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 2]] >> 24)]); + } - /* if Nb is fixed - unroll this next - loop and hard-code in the values of ri[] */ + for (i = j = 0; i < Nb; i++, j += 4) { + unpack(y[i], (uint8_t*)&buff[j]); + x[i] = y[i] = 0; /* clean up stack */ + } - for (m = j = 0; j < Nb; j++, m += 3) - { - /* This is the time-critical bit */ - y[j] = rkey[k++] ^ AEStb.rtable[(uint8_t)x[j]] ^ - ROTL8(AEStb.rtable[(uint8_t)(x[ri[m]] >> 8)])^ - ROTL16(AEStb.rtable[(uint8_t)(x[ri[m + 1]] >> 16)])^ - ROTL24(AEStb.rtable[(uint8_t)(x[ri[m + 2]] >> 24)]); - } - - t = x; - x = y; - y = t; /* swap pointers */ - } - - /* Last Round - unroll if possible */ - for (m = j = 0; j < Nb; j++, m += 3) - { - y[j] = rkey[k++] ^ (uint32_t)AEStb.rbsub[(uint8_t)x[j]] ^ - ROTL8((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m]] >> 8)])^ - ROTL16((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 1]] >> 16)])^ - ROTL24((uint32_t)AEStb.rbsub[(uint8_t)(x[ri[m + 2]] >> 24)]); - } - - for (i = j = 0; i < Nb; i++, j += 4) - { - unpack(y[i], (uint8_t*)&buff[j]); - x[i] = y[i] = 0; /* clean up stack */ - } - - return; + return; } -void SoftwareAES::setKey(const uint8_t* key) -{ - gkey(4, 4, key); -} +void SoftwareAES::setKey(const uint8_t* key) { gkey(4, 4, key); } // CBC mode decryption -void SoftwareAES::decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) -{ - uint8_t block[16]; - const uint8_t* ctext_ptr; - unsigned int blockno = 0, i; +void SoftwareAES::decrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) { + uint8_t block[16]; + const uint8_t* ctext_ptr; + unsigned int blockno = 0, i; - //fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len ); - //printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); + // fprintf( stderr,"aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len ); + // printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); - for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) + for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) { + unsigned int fraction; + + if (blockno == (len / sizeof(block))) // last block { - unsigned int fraction; + fraction = len % sizeof(block); - if (blockno == (len / sizeof(block))) // last block - { - fraction = len % sizeof(block); + if (fraction == 0) + break; - if (fraction == 0) break; + memset(block, 0, sizeof(block)); + } else + fraction = 16; - memset(block, 0, sizeof(block)); - } - else fraction = 16; + // debug_printf("block %d: fraction = %d\n", blockno, fraction); + memcpy(block, inbuf + blockno * sizeof(block), fraction); + _decrypt(block); - // debug_printf("block %d: fraction = %d\n", blockno, fraction); - memcpy(block, inbuf + blockno * sizeof(block), fraction); - _decrypt(block); + if (blockno == 0) + ctext_ptr = iv; + else + ctext_ptr = (uint8_t*)(inbuf + (blockno - 1) * sizeof(block)); - if (blockno == 0) ctext_ptr = iv; - else ctext_ptr = (uint8_t*)(inbuf + (blockno - 1) * sizeof(block)); + for (i = 0; i < fraction; i++) + outbuf[blockno * sizeof(block) + i] = ctext_ptr[i] ^ block[i]; - for (i = 0; i < fraction; i++) - outbuf[blockno * sizeof(block) + i] = - ctext_ptr[i] ^ block[i]; - - // debug_printf("Block %d output: ", blockno); - // hexdump(outbuf + blockno*sizeof(block), 16); - } + // debug_printf("Block %d output: ", blockno); + // hexdump(outbuf + blockno*sizeof(block), 16); + } } // CBC mode encryption -void SoftwareAES::encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) -{ - uint8_t block[16]; - uint8_t feedback[16]; - memcpy(feedback, iv, 16); - unsigned int blockno = 0, i; +void SoftwareAES::encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) { + uint8_t block[16]; + uint8_t feedback[16]; + memcpy(feedback, iv, 16); + unsigned int blockno = 0, i; - //printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); - //fprintf( stderr,"aes_encrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); + // printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); + // fprintf( stderr,"aes_encrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); - for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) + for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) { + unsigned int fraction; + + if (blockno == (len / sizeof(block))) // last block { - unsigned int fraction; + fraction = len % sizeof(block); - if (blockno == (len / sizeof(block))) // last block - { - fraction = len % sizeof(block); + if (fraction == 0) + break; - if (fraction == 0) break; + memset(block, 0, sizeof(block)); + } else + fraction = 16; - memset(block, 0, sizeof(block)); - } - else fraction = 16; + // debug_printf("block %d: fraction = %d\n", blockno, fraction); + memcpy(block, inbuf + blockno * sizeof(block), fraction); - // debug_printf("block %d: fraction = %d\n", blockno, fraction); - memcpy(block, inbuf + blockno * sizeof(block), fraction); + for (i = 0; i < fraction; i++) + block[i] = inbuf[blockno * sizeof(block) + i] ^ feedback[i]; - for (i = 0; i < fraction; i++) - block[i] = inbuf[blockno * sizeof(block) + i] ^ feedback[i]; - - _encrypt(block); - memcpy(feedback, block, sizeof(block)); - memcpy(outbuf + blockno * sizeof(block), block, sizeof(block)); - // debug_printf("Block %d output: ", blockno); - // hexdump(outbuf + blockno*sizeof(block), 16); - } + _encrypt(block); + memcpy(feedback, block, sizeof(block)); + memcpy(outbuf + blockno * sizeof(block), block, sizeof(block)); + // debug_printf("Block %d output: ", blockno); + // hexdump(outbuf + blockno*sizeof(block), 16); + } } #if _AES_NI #include -class NiAES : public IAES -{ - __m128i m_ekey[11]; - __m128i m_dkey[11]; +class NiAES : public IAES { + __m128i m_ekey[11]; + __m128i m_dkey[11]; + public: - void encrypt(const uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len) - { - __m128i feedback,data; - uint64_t i,j; - if (len%16) - len = len/16+1; - else - len /= 16; - feedback = _mm_loadu_si128((__m128i*)iv); - for (i=0 ; i NewAES() -{ +std::unique_ptr NewAES() { #if _AES_NI - if (HAS_AES_NI == -1) - { + if (HAS_AES_NI == -1) { #if _MSC_VER - int info[4]; - __cpuid(info, 1); - HAS_AES_NI = ((info[2] & 0x2000000) != 0); + int info[4]; + __cpuid(info, 1); + HAS_AES_NI = ((info[2] & 0x2000000) != 0); #else - unsigned int a,b,c,d; - __cpuid(1, a,b,c,d); - HAS_AES_NI = ((c & 0x2000000) != 0); + unsigned int a, b, c, d; + __cpuid(1, a, b, c, d); + HAS_AES_NI = ((c & 0x2000000) != 0); #endif - } - if (HAS_AES_NI) - return std::unique_ptr(new NiAES); - else - return std::unique_ptr(new SoftwareAES); -#else + } + if (HAS_AES_NI) + return std::unique_ptr(new NiAES); + else return std::unique_ptr(new SoftwareAES); +#else + return std::unique_ptr(new SoftwareAES); #endif } -} - +} // namespace athena diff --git a/src/athena/ALTTPFile.cpp b/src/athena/ALTTPFile.cpp index 3893ec2..ac97988 100644 --- a/src/athena/ALTTPFile.cpp +++ b/src/athena/ALTTPFile.cpp @@ -1,45 +1,30 @@ #include "athena/ALTTPFile.hpp" #include "athena/ALTTPQuest.hpp" -namespace athena -{ -ALTTPFile::ALTTPFile() -{} +namespace athena { +ALTTPFile::ALTTPFile() {} ALTTPFile::ALTTPFile(std::vector quests, std::vector backup) - : m_quests(quests) - , m_backup(backup) -{ +: m_quests(quests), m_backup(backup) {} + +void ALTTPFile::setQuest(atUint32 id, ALTTPQuest* val) { + if (id > m_quests.size()) { + atWarning("index out of range"); + return; + } + + m_quests[id] = val; } -void ALTTPFile::setQuest(atUint32 id, ALTTPQuest* val) -{ - if (id > m_quests.size()) - { - atWarning("index out of range"); - return; - } +std::vector ALTTPFile::questList() const { return m_quests; } +ALTTPQuest* ALTTPFile::quest(atUint32 id) const { + if (id > m_quests.size()) { + atWarning("index out of range"); + return nullptr; + } - m_quests[id] = val; + return m_quests[id]; } -std::vector ALTTPFile::questList() const -{ - return m_quests; -} -ALTTPQuest* ALTTPFile::quest(atUint32 id) const -{ - if (id > m_quests.size()) - { - atWarning("index out of range"); - return nullptr; - } - - return m_quests[id]; -} - -atUint32 ALTTPFile::questCount() const -{ - return (atUint32)m_quests.size(); -} -} // zelda +atUint32 ALTTPFile::questCount() const { return (atUint32)m_quests.size(); } +} // namespace athena diff --git a/src/athena/ALTTPFileReader.cpp b/src/athena/ALTTPFileReader.cpp index 2091e5c..a229848 100644 --- a/src/athena/ALTTPFileReader.cpp +++ b/src/athena/ALTTPFileReader.cpp @@ -4,233 +4,215 @@ #include #include "athena/Global.hpp" -namespace athena::io -{ +namespace athena::io { -ALTTPFileReader::ALTTPFileReader(atUint8* data, atUint64 length) - : MemoryCopyReader(data, length) -{ -} +ALTTPFileReader::ALTTPFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {} -ALTTPFileReader::ALTTPFileReader(const std::string& filename) - : MemoryCopyReader(filename) -{ -} +ALTTPFileReader::ALTTPFileReader(const std::string& filename) : MemoryCopyReader(filename) {} -ALTTPFile* ALTTPFileReader::readFile() -{ - std::vector quests; - std::vector backup; +ALTTPFile* ALTTPFileReader::readFile() { + std::vector quests; + std::vector backup; - for (atUint32 i = 0; i < 6; i++) - { - // Temporary values to use for each save - ALTTPQuest* quest = new ALTTPQuest(); - std::vector roomFlags; - std::vector owEvents; - std::vector dungeonKeys; - std::vector oldmanFlags; - std::vector unknown1; - std::vector playerName; - std::vector dungeonDeaths; + for (atUint32 i = 0; i < 6; i++) { + // Temporary values to use for each save + ALTTPQuest* quest = new ALTTPQuest(); + std::vector roomFlags; + std::vector owEvents; + std::vector dungeonKeys; + std::vector oldmanFlags; + std::vector unknown1; + std::vector playerName; + std::vector dungeonDeaths; - int j = 0x140; + int j = 0x140; - while ((j--) > 0) - { - roomFlags.push_back(readRoomFlags()); - } - - quest->setRoomFlags(roomFlags); - - j = 0x0C0; - - while ((j--) > 0) - owEvents.push_back(readOverworldEvent()); - - quest->setOverworldEvents(owEvents); - - quest->setInventory(*(ALTTPInventory*)readBytes(sizeof(ALTTPInventory)).get()); - quest->setRupeeMax(readUint16()); - quest->setRupeeCurrent(readUint16()); - quest->setCompasses(readDungeonFlags()); - quest->setBigKeys(readDungeonFlags()); - quest->setDungeonMaps(readDungeonFlags()); - quest->setWishingPond(readUint16()); - quest->setHealthMax(readByte()); - quest->setHealth(readByte()); - quest->setMagicPower(readByte()); - quest->setKeys(readByte()); - quest->setBombUpgrades(readByte()); - quest->setArrowUpgrades(readByte()); - quest->setHealthFiller(readByte()); - quest->setMagicFiller(readByte()); - atUint8 pendantsByte = readUByte(); - ALTTPPendants pendants; - pendants.Courage = pendantsByte & 1; - pendants.Wisdom = (pendantsByte >> 1) & 1; - pendants.Power = (pendantsByte >> 2) & 1; - pendants.Unused1 = false; - pendants.Unused2 = false; - pendants.Unused3 = false; - pendants.Unused4 = false; - pendants.Unused5 = false; - quest->setPendants(pendants); - quest->setBombFiller(readByte()); - quest->setArrowFiller(readByte()); - quest->setArrows(readByte()); - seek(1); - atUint8 abilitiesByte = readUByte(); - ALTTPAbilities abilities; - abilities.Nothing = abilitiesByte & 1; - abilities.Swim = (abilitiesByte >> 1) & 1; - abilities.Dash = (abilitiesByte >> 2) & 1; - abilities.Pull = (abilitiesByte >> 3) & 1; - abilities.Unknown1 = (abilitiesByte >> 4) & 1; - abilities.Talk = (abilitiesByte >> 5) & 1; - abilities.Read = (abilitiesByte >> 6) & 1; - abilities.Unknown2 = (abilitiesByte >> 7) & 1; - quest->setAbilityFlags(abilities); - quest->setCrystals(*(ALTTPCrystals*)readBytes(sizeof(ALTTPCrystals)).get()); - quest->setMagicUsage(*(ALTTPMagicUsage*)readBytes(sizeof(ALTTPMagicUsage)).get()); - - j = 0x10; - - while ((j--) > 0) - { - dungeonKeys.push_back(readByte()); - } - - quest->setDungeonKeys(dungeonKeys); - seek(0x039); - quest->setProgressIndicator((ALTTPProgressIndicator)readByte()); - quest->setProgressFlags1(*(ALTTPProgressFlags1*)readBytes(sizeof(ALTTPProgressFlags1)).get()); - quest->setMapIcon((ALTTPMapIcon)readByte()); - quest->setStartLocation((ALTTPStartLocation)readByte()); - quest->setProgressFlags2(*(ALTTPProgressFlags2*)readBytes(sizeof(ALTTPProgressFlags2)).get()); - quest->setLightDarkWorldIndicator(*(ALTTPLightDarkWorldIndicator*)readBytes(1).get()); - seek(1); - quest->setTagAlong((ALTTPTagAlong)readByte()); - - j = 6; - - while ((j--) > 0) - { - oldmanFlags.push_back(readByte()); - } - - quest->setOldManFlags(oldmanFlags); - quest->setBombFlag(readByte()); - - j = 5; - - while ((j--) > 0) - { - unknown1.push_back(readByte()); - } - - quest->setUnknown1(unknown1); - - j = 6; - - while ((j--) > 0) - { - playerName.push_back(readUint16()); - } - - quest->setPlayerName(playerName); - quest->setValid((readUint16() == 0x55AA)); - - j = 0x0D; - - while ((j--) > 0) - { - dungeonDeaths.push_back(readUint16()); - } - - quest->setDungeonDeathTotals(dungeonDeaths); - - quest->setUnknown2(readUint16()); - quest->setDeathSaveCount(readUint16()); - quest->setPostGameDeathCounter(readInt16()); - - seek(0xF7); - - quest->setChecksum(readUint16()); - - if (i < 3) - quests.push_back(quest); - else - backup.push_back(quest); + while ((j--) > 0) { + roomFlags.push_back(readRoomFlags()); } - return new ALTTPFile(quests, backup); + quest->setRoomFlags(roomFlags); + + j = 0x0C0; + + while ((j--) > 0) + owEvents.push_back(readOverworldEvent()); + + quest->setOverworldEvents(owEvents); + + quest->setInventory(*(ALTTPInventory*)readBytes(sizeof(ALTTPInventory)).get()); + quest->setRupeeMax(readUint16()); + quest->setRupeeCurrent(readUint16()); + quest->setCompasses(readDungeonFlags()); + quest->setBigKeys(readDungeonFlags()); + quest->setDungeonMaps(readDungeonFlags()); + quest->setWishingPond(readUint16()); + quest->setHealthMax(readByte()); + quest->setHealth(readByte()); + quest->setMagicPower(readByte()); + quest->setKeys(readByte()); + quest->setBombUpgrades(readByte()); + quest->setArrowUpgrades(readByte()); + quest->setHealthFiller(readByte()); + quest->setMagicFiller(readByte()); + atUint8 pendantsByte = readUByte(); + ALTTPPendants pendants; + pendants.Courage = pendantsByte & 1; + pendants.Wisdom = (pendantsByte >> 1) & 1; + pendants.Power = (pendantsByte >> 2) & 1; + pendants.Unused1 = false; + pendants.Unused2 = false; + pendants.Unused3 = false; + pendants.Unused4 = false; + pendants.Unused5 = false; + quest->setPendants(pendants); + quest->setBombFiller(readByte()); + quest->setArrowFiller(readByte()); + quest->setArrows(readByte()); + seek(1); + atUint8 abilitiesByte = readUByte(); + ALTTPAbilities abilities; + abilities.Nothing = abilitiesByte & 1; + abilities.Swim = (abilitiesByte >> 1) & 1; + abilities.Dash = (abilitiesByte >> 2) & 1; + abilities.Pull = (abilitiesByte >> 3) & 1; + abilities.Unknown1 = (abilitiesByte >> 4) & 1; + abilities.Talk = (abilitiesByte >> 5) & 1; + abilities.Read = (abilitiesByte >> 6) & 1; + abilities.Unknown2 = (abilitiesByte >> 7) & 1; + quest->setAbilityFlags(abilities); + quest->setCrystals(*(ALTTPCrystals*)readBytes(sizeof(ALTTPCrystals)).get()); + quest->setMagicUsage(*(ALTTPMagicUsage*)readBytes(sizeof(ALTTPMagicUsage)).get()); + + j = 0x10; + + while ((j--) > 0) { + dungeonKeys.push_back(readByte()); + } + + quest->setDungeonKeys(dungeonKeys); + seek(0x039); + quest->setProgressIndicator((ALTTPProgressIndicator)readByte()); + quest->setProgressFlags1(*(ALTTPProgressFlags1*)readBytes(sizeof(ALTTPProgressFlags1)).get()); + quest->setMapIcon((ALTTPMapIcon)readByte()); + quest->setStartLocation((ALTTPStartLocation)readByte()); + quest->setProgressFlags2(*(ALTTPProgressFlags2*)readBytes(sizeof(ALTTPProgressFlags2)).get()); + quest->setLightDarkWorldIndicator(*(ALTTPLightDarkWorldIndicator*)readBytes(1).get()); + seek(1); + quest->setTagAlong((ALTTPTagAlong)readByte()); + + j = 6; + + while ((j--) > 0) { + oldmanFlags.push_back(readByte()); + } + + quest->setOldManFlags(oldmanFlags); + quest->setBombFlag(readByte()); + + j = 5; + + while ((j--) > 0) { + unknown1.push_back(readByte()); + } + + quest->setUnknown1(unknown1); + + j = 6; + + while ((j--) > 0) { + playerName.push_back(readUint16()); + } + + quest->setPlayerName(playerName); + quest->setValid((readUint16() == 0x55AA)); + + j = 0x0D; + + while ((j--) > 0) { + dungeonDeaths.push_back(readUint16()); + } + + quest->setDungeonDeathTotals(dungeonDeaths); + + quest->setUnknown2(readUint16()); + quest->setDeathSaveCount(readUint16()); + quest->setPostGameDeathCounter(readInt16()); + + seek(0xF7); + + quest->setChecksum(readUint16()); + + if (i < 3) + quests.push_back(quest); + else + backup.push_back(quest); + } + + return new ALTTPFile(quests, backup); } -ALTTPRoomFlags* ALTTPFileReader::readRoomFlags() -{ - ALTTPRoomFlags* flags = new ALTTPRoomFlags; - atUint8 flagsByte = readUByte(); - flags->Chest1 = flagsByte & 1; - flags->Chest2 = (flagsByte >> 1) & 1; - flags->Chest3 = (flagsByte >> 2) & 1; - flags->Chest4 = (flagsByte >> 3) & 1; - flags->Quadrant1 = (flagsByte >> 4) & 1; - flags->Quadrant2 = (flagsByte >> 5) & 1; - flags->Quadrant3 = (flagsByte >> 6) & 1; - flags->Quadrant4 = (flagsByte >> 7) & 1; - flagsByte = readUByte(); - flags->Door1 = flagsByte & 1; - flags->Door2 = (flagsByte >> 1) & 1; - flags->Door3 = (flagsByte >> 2) & 1; - flags->Door4 = (flagsByte >> 3) & 1; - flags->BossBattleWon = (flagsByte >> 4) & 1; - flags->Key = (flagsByte >> 5) & 1; - flags->KeyOrChest = (flagsByte >> 6) & 1; - flags->ChestOrTile = (flagsByte >> 7) & 1; +ALTTPRoomFlags* ALTTPFileReader::readRoomFlags() { + ALTTPRoomFlags* flags = new ALTTPRoomFlags; + atUint8 flagsByte = readUByte(); + flags->Chest1 = flagsByte & 1; + flags->Chest2 = (flagsByte >> 1) & 1; + flags->Chest3 = (flagsByte >> 2) & 1; + flags->Chest4 = (flagsByte >> 3) & 1; + flags->Quadrant1 = (flagsByte >> 4) & 1; + flags->Quadrant2 = (flagsByte >> 5) & 1; + flags->Quadrant3 = (flagsByte >> 6) & 1; + flags->Quadrant4 = (flagsByte >> 7) & 1; + flagsByte = readUByte(); + flags->Door1 = flagsByte & 1; + flags->Door2 = (flagsByte >> 1) & 1; + flags->Door3 = (flagsByte >> 2) & 1; + flags->Door4 = (flagsByte >> 3) & 1; + flags->BossBattleWon = (flagsByte >> 4) & 1; + flags->Key = (flagsByte >> 5) & 1; + flags->KeyOrChest = (flagsByte >> 6) & 1; + flags->ChestOrTile = (flagsByte >> 7) & 1; - return flags; + return flags; } -ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent() -{ - ALTTPOverworldEvent* event = new ALTTPOverworldEvent; - atUint8 flagsByte = readUByte(); - event->Unused1 = flagsByte & 1; - event->HeartPiece = (flagsByte >> 1) & 1; - event->Overlay = (flagsByte >> 2) & 1; - event->Unused2 = (flagsByte >> 3) & 1; - event->Unused3 = (flagsByte >> 4) & 1; - event->Unused4 = (flagsByte >> 5) & 1; - event->Set = (flagsByte >> 6) & 1; - event->Unused5 = (flagsByte >> 7) & 1; - return event; +ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent() { + ALTTPOverworldEvent* event = new ALTTPOverworldEvent; + atUint8 flagsByte = readUByte(); + event->Unused1 = flagsByte & 1; + event->HeartPiece = (flagsByte >> 1) & 1; + event->Overlay = (flagsByte >> 2) & 1; + event->Unused2 = (flagsByte >> 3) & 1; + event->Unused3 = (flagsByte >> 4) & 1; + event->Unused4 = (flagsByte >> 5) & 1; + event->Set = (flagsByte >> 6) & 1; + event->Unused5 = (flagsByte >> 7) & 1; + return event; } -ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags() -{ - ALTTPDungeonItemFlags flags; - atUint8 flagsByte = readUByte(); - flags.Unused1 = flagsByte & 1; - flags.Unused2 = (flagsByte >> 1) & 1; - flags.GanonsTower = (flagsByte >> 2) & 1; - flags.TurtleRock = (flagsByte >> 3) & 1; - flags.GargoylesDomain = (flagsByte >> 4) & 1; - flags.TowerOfHera = (flagsByte >> 5) & 1; - flags.IcePalace = (flagsByte >> 6) & 1; - flags.SkullWoods = (flagsByte >> 7) & 1; - flagsByte = readUByte(); - flags.MiseryMire = flagsByte & 1; - flags.DarkPalace = (flagsByte >> 1) & 1; - flags.SwampPalace = (flagsByte >> 2) & 1; - flags.HyruleCastle2 = (flagsByte >> 3) & 1; - flags.DesertPalace = (flagsByte >> 4) & 1; - flags.EasternPalace = (flagsByte >> 5) & 1; - flags.HyruleCastle = (flagsByte >> 6) & 1; - flags.SewerPassage = (flagsByte >> 7) & 1; +ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags() { + ALTTPDungeonItemFlags flags; + atUint8 flagsByte = readUByte(); + flags.Unused1 = flagsByte & 1; + flags.Unused2 = (flagsByte >> 1) & 1; + flags.GanonsTower = (flagsByte >> 2) & 1; + flags.TurtleRock = (flagsByte >> 3) & 1; + flags.GargoylesDomain = (flagsByte >> 4) & 1; + flags.TowerOfHera = (flagsByte >> 5) & 1; + flags.IcePalace = (flagsByte >> 6) & 1; + flags.SkullWoods = (flagsByte >> 7) & 1; + flagsByte = readUByte(); + flags.MiseryMire = flagsByte & 1; + flags.DarkPalace = (flagsByte >> 1) & 1; + flags.SwampPalace = (flagsByte >> 2) & 1; + flags.HyruleCastle2 = (flagsByte >> 3) & 1; + flags.DesertPalace = (flagsByte >> 4) & 1; + flags.EasternPalace = (flagsByte >> 5) & 1; + flags.HyruleCastle = (flagsByte >> 6) & 1; + flags.SewerPassage = (flagsByte >> 7) & 1; - atDebug("%x %x", flags.flags1, flags.flags2); - return flags; + atDebug("%x %x", flags.flags1, flags.flags2); + return flags; } -} // io +} // namespace athena::io diff --git a/src/athena/ALTTPFileWriter.cpp b/src/athena/ALTTPFileWriter.cpp index 10f68d1..14dd67b 100644 --- a/src/athena/ALTTPFileWriter.cpp +++ b/src/athena/ALTTPFileWriter.cpp @@ -3,221 +3,204 @@ #include "athena/ALTTPQuest.hpp" #include -namespace athena -{ +namespace athena { -namespace io -{ +namespace io { -ALTTPFileWriter::ALTTPFileWriter(atUint8* data, atUint64 length) - : MemoryCopyWriter(data, length) -{ -} +ALTTPFileWriter::ALTTPFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {} -ALTTPFileWriter::ALTTPFileWriter(const std::string& filename) - : MemoryCopyWriter(filename) -{ -} +ALTTPFileWriter::ALTTPFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {} -void ALTTPFileWriter::writeFile(ALTTPFile* file) -{ - ALTTPQuest* quest = NULL; +void ALTTPFileWriter::writeFile(ALTTPFile* file) { + ALTTPQuest* quest = NULL; - for (atUint32 i = 0; i < 6; i++) - { - if (i < 3) - quest = file->quest(i); - else - quest = file->quest(i - 3); + for (atUint32 i = 0; i < 6; i++) { + if (i < 3) + quest = file->quest(i); + else + quest = file->quest(i - 3); - for (int j = 0; j < 0x140; j++) - { - writeRoomFlags(quest->roomFlags(j)); - } - - for (int j = 0; j < 0x0C0; j++) - { - writeOverworldEvent(quest->overworldEvent(j)); - } - - writeBytes((atInt8*)&quest->inventory(), sizeof(ALTTPInventory)); - writeUint16(quest->rupeeMax()); - writeUint16(quest->rupeeCurrent()); - writeDungeonItems(quest->compasses()); - writeDungeonItems(quest->bigKeys()); - writeDungeonItems(quest->dungeonMaps()); - writeUint16(quest->wishingPond()); - writeByte(quest->healthMax()); - writeByte(quest->health()); - writeByte(quest->magicPower()); - writeByte(quest->keys()); - writeByte(quest->bombUpgrades()); - writeByte(quest->arrowUpgrades()); - writeByte(quest->healthFiller()); - writeByte(quest->magicFiller()); - ALTTPPendants pendants = quest->pendants(); - atUint8 pendantsByte = 0; - pendantsByte |= pendants.Courage; - pendantsByte |= pendants.Wisdom << 1; - pendantsByte |= pendants.Power << 2; - writeUByte(pendantsByte); - writeByte(quest->bombFiller()); - writeByte(quest->arrowFiller()); - writeByte(quest->arrows()); - seek(1); - ALTTPAbilities abilities = quest->abilityFlags(); - atUint8 abilitiesByte = 0; - abilitiesByte |= abilities.Nothing; - abilitiesByte |= abilities.Swim << 1; - abilitiesByte |= abilities.Dash << 2; - abilitiesByte |= abilities.Pull << 3; - abilitiesByte |= abilities.Unknown1 << 4; - abilitiesByte |= abilities.Talk << 5; - abilitiesByte |= abilities.Read << 6; - abilitiesByte |= abilities.Unknown2 << 7; - writeUByte(abilitiesByte); - ALTTPCrystals crystals = quest->crystals(); - writeBytes((atInt8*)&crystals, sizeof(ALTTPCrystals)); - ALTTPMagicUsage magicUsage = quest->magicUsage(); - writeBytes((atInt8*)&magicUsage, sizeof(ALTTPMagicUsage)); - - for (int j = 0; j < 0x010; j++) - writeByte(quest->dungeonKeys(j)); - - seek(0x039); - writeByte((atInt8)quest->progressIndicator()); - ALTTPProgressFlags1 progress1 = quest->progressFlags1(); - writeBytes((atInt8*)&progress1, sizeof(ALTTPProgressFlags1)); - writeByte(quest->mapIcon()); - writeByte(quest->startLocation()); - ALTTPProgressFlags2 progress2 = quest->progressFlags2(); - writeBytes((atInt8*)&progress2, sizeof(ALTTPProgressFlags2)); - ALTTPLightDarkWorldIndicator indicator = quest->lightDarkWorldIndicator(); - writeBytes((atInt8*)&indicator, 1); - seek(1); - writeByte(quest->tagAlong()); - - for (int j = 0; j < 6; j++) - writeByte(quest->oldManFlag(j)); - - writeByte(quest->bombFlag()); - - for (int j = 0; j < 5; j++) - writeByte(quest->unknown1(j)); - - for (int j = 0; j < 6; j++) - writeUint16(quest->playerName()[j]); - - writeUint16((quest->valid() == true ? 0x55AA : 0)); - - for (int j = 0; j < 0x0D; j++) - writeUint16(quest->dungeonDeathTotal(j)); - - - writeUint16(quest->unknown2()); - writeUint16(quest->deathSaveCount()); - writeUint16(quest->postGameDeathCounter()); - - seek(0xF7); - writeUint16(calculateChecksum(i)); + for (int j = 0; j < 0x140; j++) { + writeRoomFlags(quest->roomFlags(j)); } + + for (int j = 0; j < 0x0C0; j++) { + writeOverworldEvent(quest->overworldEvent(j)); + } + + writeBytes((atInt8*)&quest->inventory(), sizeof(ALTTPInventory)); + writeUint16(quest->rupeeMax()); + writeUint16(quest->rupeeCurrent()); + writeDungeonItems(quest->compasses()); + writeDungeonItems(quest->bigKeys()); + writeDungeonItems(quest->dungeonMaps()); + writeUint16(quest->wishingPond()); + writeByte(quest->healthMax()); + writeByte(quest->health()); + writeByte(quest->magicPower()); + writeByte(quest->keys()); + writeByte(quest->bombUpgrades()); + writeByte(quest->arrowUpgrades()); + writeByte(quest->healthFiller()); + writeByte(quest->magicFiller()); + ALTTPPendants pendants = quest->pendants(); + atUint8 pendantsByte = 0; + pendantsByte |= pendants.Courage; + pendantsByte |= pendants.Wisdom << 1; + pendantsByte |= pendants.Power << 2; + writeUByte(pendantsByte); + writeByte(quest->bombFiller()); + writeByte(quest->arrowFiller()); + writeByte(quest->arrows()); + seek(1); + ALTTPAbilities abilities = quest->abilityFlags(); + atUint8 abilitiesByte = 0; + abilitiesByte |= abilities.Nothing; + abilitiesByte |= abilities.Swim << 1; + abilitiesByte |= abilities.Dash << 2; + abilitiesByte |= abilities.Pull << 3; + abilitiesByte |= abilities.Unknown1 << 4; + abilitiesByte |= abilities.Talk << 5; + abilitiesByte |= abilities.Read << 6; + abilitiesByte |= abilities.Unknown2 << 7; + writeUByte(abilitiesByte); + ALTTPCrystals crystals = quest->crystals(); + writeBytes((atInt8*)&crystals, sizeof(ALTTPCrystals)); + ALTTPMagicUsage magicUsage = quest->magicUsage(); + writeBytes((atInt8*)&magicUsage, sizeof(ALTTPMagicUsage)); + + for (int j = 0; j < 0x010; j++) + writeByte(quest->dungeonKeys(j)); + + seek(0x039); + writeByte((atInt8)quest->progressIndicator()); + ALTTPProgressFlags1 progress1 = quest->progressFlags1(); + writeBytes((atInt8*)&progress1, sizeof(ALTTPProgressFlags1)); + writeByte(quest->mapIcon()); + writeByte(quest->startLocation()); + ALTTPProgressFlags2 progress2 = quest->progressFlags2(); + writeBytes((atInt8*)&progress2, sizeof(ALTTPProgressFlags2)); + ALTTPLightDarkWorldIndicator indicator = quest->lightDarkWorldIndicator(); + writeBytes((atInt8*)&indicator, 1); + seek(1); + writeByte(quest->tagAlong()); + + for (int j = 0; j < 6; j++) + writeByte(quest->oldManFlag(j)); + + writeByte(quest->bombFlag()); + + for (int j = 0; j < 5; j++) + writeByte(quest->unknown1(j)); + + for (int j = 0; j < 6; j++) + writeUint16(quest->playerName()[j]); + + writeUint16((quest->valid() == true ? 0x55AA : 0)); + + for (int j = 0; j < 0x0D; j++) + writeUint16(quest->dungeonDeathTotal(j)); + + writeUint16(quest->unknown2()); + writeUint16(quest->deathSaveCount()); + writeUint16(quest->postGameDeathCounter()); + + seek(0xF7); + writeUint16(calculateChecksum(i)); + } } -void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags) -{ - atUint8 flagsByte = 0; - flagsByte |= flags->Chest1; - flagsByte |= flags->Chest2 << 1; - flagsByte |= flags->Chest3 << 2; - flagsByte |= flags->Chest4 << 3; - flagsByte |= flags->Quadrant1 << 4; - flagsByte |= flags->Quadrant2 << 5; - flagsByte |= flags->Quadrant3 << 6; - flagsByte |= flags->Quadrant4 << 7; - writeUByte(flagsByte); - flagsByte = 0; - flagsByte |= flags->Door1; - flagsByte |= flags->Door2 << 1; - flagsByte |= flags->Door3 << 2; - flagsByte |= flags->Door4 << 3; - flagsByte |= flags->BossBattleWon << 4; - flagsByte |= flags->Key << 5; - flagsByte |= flags->KeyOrChest << 6; - flagsByte |= flags->ChestOrTile << 7; - writeUByte(flagsByte); +void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags) { + atUint8 flagsByte = 0; + flagsByte |= flags->Chest1; + flagsByte |= flags->Chest2 << 1; + flagsByte |= flags->Chest3 << 2; + flagsByte |= flags->Chest4 << 3; + flagsByte |= flags->Quadrant1 << 4; + flagsByte |= flags->Quadrant2 << 5; + flagsByte |= flags->Quadrant3 << 6; + flagsByte |= flags->Quadrant4 << 7; + writeUByte(flagsByte); + flagsByte = 0; + flagsByte |= flags->Door1; + flagsByte |= flags->Door2 << 1; + flagsByte |= flags->Door3 << 2; + flagsByte |= flags->Door4 << 3; + flagsByte |= flags->BossBattleWon << 4; + flagsByte |= flags->Key << 5; + flagsByte |= flags->KeyOrChest << 6; + flagsByte |= flags->ChestOrTile << 7; + writeUByte(flagsByte); } -void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event) -{ - atUint8 flagsByte = 0; - flagsByte |= event->Unused1; - flagsByte |= event->HeartPiece << 1; - flagsByte |= event->Overlay << 2; - flagsByte |= event->Unused2 << 3; - flagsByte |= event->Unused3 << 4; - flagsByte |= event->Unused4 << 5; - flagsByte |= event->Set << 6; - flagsByte |= event->Unused5 << 7; - writeUByte(flagsByte); +void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event) { + atUint8 flagsByte = 0; + flagsByte |= event->Unused1; + flagsByte |= event->HeartPiece << 1; + flagsByte |= event->Overlay << 2; + flagsByte |= event->Unused2 << 3; + flagsByte |= event->Unused3 << 4; + flagsByte |= event->Unused4 << 5; + flagsByte |= event->Set << 6; + flagsByte |= event->Unused5 << 7; + writeUByte(flagsByte); } -void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags) -{ - atUint8 flagsByte = 0; - flagsByte |= flags.Unused1; - flagsByte |= flags.Unused2 << 1; - flagsByte |= flags.GanonsTower << 2; - flagsByte |= flags.TurtleRock << 3; - flagsByte |= flags.TowerOfHera << 4; - flagsByte |= flags.IcePalace << 5; - flagsByte |= flags.SkullWoods << 6; - flagsByte |= flags.MiseryMire << 7; - writeUByte(flagsByte); - flagsByte = 0; - flagsByte |= flags.DarkPalace; - flagsByte |= flags.SwampPalace << 1; - flagsByte |= flags.HyruleCastle2 << 2; - flagsByte |= flags.DesertPalace << 3; - flagsByte |= flags.EasternPalace << 4; - flagsByte |= flags.HyruleCastle << 5; - flagsByte |= flags.SewerPassage << 6; - writeUByte(flagsByte); +void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags) { + atUint8 flagsByte = 0; + flagsByte |= flags.Unused1; + flagsByte |= flags.Unused2 << 1; + flagsByte |= flags.GanonsTower << 2; + flagsByte |= flags.TurtleRock << 3; + flagsByte |= flags.TowerOfHera << 4; + flagsByte |= flags.IcePalace << 5; + flagsByte |= flags.SkullWoods << 6; + flagsByte |= flags.MiseryMire << 7; + writeUByte(flagsByte); + flagsByte = 0; + flagsByte |= flags.DarkPalace; + flagsByte |= flags.SwampPalace << 1; + flagsByte |= flags.HyruleCastle2 << 2; + flagsByte |= flags.DesertPalace << 3; + flagsByte |= flags.EasternPalace << 4; + flagsByte |= flags.HyruleCastle << 5; + flagsByte |= flags.SewerPassage << 6; + writeUByte(flagsByte); } -atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game) -{ - /* - * ALTTP's checksum is very basic - * It adds each word up and then subtracts the sum from 0x5a5a - * The number seems pretty arbitrary, but it enables the game to differentiate - * it from a number that just happens to equal the sum outright, preventing "false positives." - * - * Ignoring the algorithm for figuring out it's position in the buffer the equation is basically: - * s = s + w - * s = (0x5a5a - s); - * s == sum - * w == current word - * - * For those who don't know a word is a two byte pair, i.e 0xFF and 0xFE constitutes a word. - */ +atUint16 ALTTPFileWriter::calculateChecksum(atUint32 game) { + /* + * ALTTP's checksum is very basic + * It adds each word up and then subtracts the sum from 0x5a5a + * The number seems pretty arbitrary, but it enables the game to differentiate + * it from a number that just happens to equal the sum outright, preventing "false positives." + * + * Ignoring the algorithm for figuring out it's position in the buffer the equation is basically: + * s = s + w + * s = (0x5a5a - s); + * s == sum + * w == current word + * + * For those who don't know a word is a two byte pair, i.e 0xFF and 0xFE constitutes a word. + */ - // First we start at 0 - atUint16 sum = 0; + // First we start at 0 + atUint16 sum = 0; - for (atUint32 i = 0; i < 0x4FE; i += 2) - // Add each word one by one - sum += *(atUint16*)(m_data + (i + (0x500 * game))); + for (atUint32 i = 0; i < 0x4FE; i += 2) + // Add each word one by one + sum += *(atUint16*)(m_data + (i + (0x500 * game))); - // Subtract it from 0x5a5a to get our true checksum - return (0x5a5a - sum); + // Subtract it from 0x5a5a to get our true checksum + return (0x5a5a - sum); - /* - * There is one caveat to this algorithm however, - * It makes it difficult to manually edit this in a hex editor since it's not a common - * algorithm and most hexeditor with built in checksum calculators won't have it, however it's - * it's extremely basic, making it a non-issue really. - */ + /* + * There is one caveat to this algorithm however, + * It makes it difficult to manually edit this in a hex editor since it's not a common + * algorithm and most hexeditor with built in checksum calculators won't have it, however it's + * it's extremely basic, making it a non-issue really. + */ } -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/src/athena/ALTTPQuest.cpp b/src/athena/ALTTPQuest.cpp index 3301403..e2ef984 100644 --- a/src/athena/ALTTPQuest.cpp +++ b/src/athena/ALTTPQuest.cpp @@ -1,747 +1,437 @@ #include "athena/ALTTPQuest.hpp" #include -namespace athena -{ +namespace athena { -ALTTPQuest::ALTTPQuest() -{ +ALTTPQuest::ALTTPQuest() {} + +ALTTPQuest::~ALTTPQuest() { + m_roomFlags.clear(); + m_overworldEvents.clear(); + m_oldManFlags.clear(); + m_playerName.clear(); + m_unknown1.clear(); } -ALTTPQuest::~ALTTPQuest() -{ - m_roomFlags.clear(); - m_overworldEvents.clear(); - m_oldManFlags.clear(); - m_playerName.clear(); - m_unknown1.clear(); +void ALTTPQuest::setRoomFlags(std::vector rf) { m_roomFlags = rf; } + +void ALTTPQuest::setRoomFlags(ALTTPRoomFlags* rf, atUint32 id) { m_roomFlags[id] = rf; } + +std::vector ALTTPQuest::roomFlags() { return m_roomFlags; } + +ALTTPRoomFlags* ALTTPQuest::roomFlags(atUint32 id) { return m_roomFlags[id]; } + +void ALTTPQuest::setOverworldEvents(std::vector ow) { m_overworldEvents = ow; } + +void ALTTPQuest::setOverworldEvents(ALTTPOverworldEvent* ow, atUint32 id) { m_overworldEvents[id] = ow; } + +std::vector ALTTPQuest::overworldEvents() const { return m_overworldEvents; } + +ALTTPOverworldEvent* ALTTPQuest::overworldEvent(atUint32 id) const { + if (id > m_overworldEvents.size() - 1) { + atWarning("index out of range"); + return nullptr; + } + + return m_overworldEvents[id]; } -void ALTTPQuest::setRoomFlags(std::vector rf) -{ - m_roomFlags = rf; +void ALTTPQuest::setInventory(const ALTTPInventory& inv) { m_inventory = inv; } + +const ALTTPInventory& ALTTPQuest::inventory() const { return m_inventory; } + +void ALTTPQuest::setRupeeMax(atUint16 val) { m_rupeeMax = val; } + +atUint16 ALTTPQuest::rupeeMax() const { return m_rupeeMax; } + +void ALTTPQuest::setRupeeCurrent(atUint16 val) { m_rupeeCurrent = val; } + +atUint16 ALTTPQuest::rupeeCurrent() const { return m_rupeeCurrent; } + +void ALTTPQuest::setCompasses(ALTTPDungeonItemFlags flags) { m_compasses = flags; } + +ALTTPDungeonItemFlags ALTTPQuest::compasses() const { return m_compasses; } + +void ALTTPQuest::setBigKeys(ALTTPDungeonItemFlags flags) { m_bigKeys = flags; } + +ALTTPDungeonItemFlags ALTTPQuest::bigKeys() const { return m_bigKeys; } + +void ALTTPQuest::setDungeonMaps(ALTTPDungeonItemFlags flags) { m_dungeonMaps = flags; } + +ALTTPDungeonItemFlags ALTTPQuest::dungeonMaps() const { return m_dungeonMaps; } + +void ALTTPQuest::setWishingPond(atUint16 val) { m_wishingPond = val; } + +atUint16 ALTTPQuest::wishingPond() const { return m_wishingPond; } + +void ALTTPQuest::setHealthMax(atUint8 val) { m_healthMax = val; } + +atUint8 ALTTPQuest::healthMax() const { return m_healthMax; } + +void ALTTPQuest::setHealth(atUint8 val) { m_health = val; } + +atUint8 ALTTPQuest::health() const { return m_health; } + +void ALTTPQuest::setMagicPower(atUint8 val) { m_magicPower = val; } + +atUint8 ALTTPQuest::magicPower() const { return m_magicPower; } + +void ALTTPQuest::setKeys(atUint8 val) { m_keys = val; } + +atUint8 ALTTPQuest::keys() const { return m_keys; } + +void ALTTPQuest::setBombUpgrades(atUint8 val) { m_bombUpgrades = val; } + +atUint8 ALTTPQuest::bombUpgrades() const { return m_bombUpgrades; } + +void ALTTPQuest::setArrowUpgrades(atUint8 val) { m_arrowUpgrades = val; } + +atUint8 ALTTPQuest::arrowUpgrades() const { return m_arrowUpgrades; } + +void ALTTPQuest::setHealthFiller(atUint8 val) { m_heartFiller = val; } + +atUint8 ALTTPQuest::healthFiller() const { return m_heartFiller; } +void ALTTPQuest::setMagicFiller(atUint8 val) { m_heartFiller = val; } + +atUint8 ALTTPQuest::magicFiller() const { return m_heartFiller; } + +void ALTTPQuest::setPendants(ALTTPPendants val) { m_pendants = val; } + +ALTTPPendants ALTTPQuest::pendants() const { return m_pendants; } + +void ALTTPQuest::setBombFiller(atUint8 val) { m_bombFiller = val; } + +atUint8 ALTTPQuest::bombFiller() const { return m_bombFiller; } + +void ALTTPQuest::setArrowFiller(atUint8 val) { m_arrowFiller = val; } + +atUint8 ALTTPQuest::arrowFiller() const { return m_arrowFiller; } +void ALTTPQuest::setArrows(atUint8 val) { m_arrows = val; } + +atUint8 ALTTPQuest::arrows() const { return m_arrows; } + +void ALTTPQuest::setAbilityFlags(ALTTPAbilities val) { m_abilityFlags = val; } + +ALTTPAbilities ALTTPQuest::abilityFlags() const { return m_abilityFlags; } + +void ALTTPQuest::setCrystals(ALTTPCrystals val) { m_crystals = val; } + +ALTTPCrystals ALTTPQuest::crystals() const { return m_crystals; } + +void ALTTPQuest::setMagicUsage(ALTTPMagicUsage val) { m_magicUsage = val; } + +ALTTPMagicUsage ALTTPQuest::magicUsage() const { return m_magicUsage; } + +void ALTTPQuest::setDungeonKeys(std::vector val) { m_dungeonKeys = val; } + +void ALTTPQuest::setDungeonKeys(atUint32 id, atUint8 val) { + if (id > m_dungeonKeys.size() - 1) { + atWarning("index out of range"); + return; + } + + m_dungeonKeys[id] = val; } -void ALTTPQuest::setRoomFlags(ALTTPRoomFlags* rf, atUint32 id) -{ - m_roomFlags[id] = rf; +atUint8 ALTTPQuest::dungeonKeys(atUint32 id) const { + if (id > m_dungeonKeys.size() - 1) { + atWarning("index out of range"); + return 0; + } + + return m_dungeonKeys[id]; } -std::vector ALTTPQuest::roomFlags() -{ - return m_roomFlags; +atUint32 ALTTPQuest::dungeonCount() const { return (atUint32)m_dungeonKeys.size(); } + +void ALTTPQuest::setProgressIndicator(ALTTPProgressIndicator val) { m_progressIndicator = val; } + +ALTTPProgressIndicator ALTTPQuest::progressIndicator() const { return m_progressIndicator; } + +void ALTTPQuest::setProgressFlags1(ALTTPProgressFlags1 val) { m_progressFlags1 = val; } + +ALTTPProgressFlags1 ALTTPQuest::progressFlags1() const { return m_progressFlags1; } + +void ALTTPQuest::setMapIcon(ALTTPMapIcon val) { m_mapIcon = val; } + +ALTTPMapIcon ALTTPQuest::mapIcon() const { return m_mapIcon; } + +void ALTTPQuest::setStartLocation(ALTTPStartLocation val) { m_startLocation = val; } + +ALTTPStartLocation ALTTPQuest::startLocation() const { return m_startLocation; } + +void ALTTPQuest::setProgressFlags2(ALTTPProgressFlags2 val) { m_progressFlags2 = val; } + +ALTTPProgressFlags2 ALTTPQuest::progressFlags2() const { return m_progressFlags2; } + +void ALTTPQuest::setLightDarkWorldIndicator(ALTTPLightDarkWorldIndicator val) { m_lightDarkWorldIndicator = val; } + +ALTTPLightDarkWorldIndicator ALTTPQuest::lightDarkWorldIndicator() const { return m_lightDarkWorldIndicator; } + +void ALTTPQuest::setTagAlong(ALTTPTagAlong val) { m_tagAlong = val; } + +ALTTPTagAlong ALTTPQuest::tagAlong() const { return m_tagAlong; } + +void ALTTPQuest::setOldManFlags(std::vector flags) { m_oldManFlags = flags; } + +void ALTTPQuest::setOldManFlag(atUint32 id, atUint8 val) { + if (id > m_oldManFlags.size() - 1) { + atWarning("index out of range"); + return; + } + + m_oldManFlags[id] = val; } -ALTTPRoomFlags* ALTTPQuest::roomFlags(atUint32 id) -{ - return m_roomFlags[id]; +atUint8 ALTTPQuest::oldManFlag(atUint32 id) { + if (id > m_oldManFlags.size() - 1) { + atWarning("index out of range"); + return 0; + } + return m_oldManFlags[id]; } -void ALTTPQuest::setOverworldEvents(std::vector ow) -{ - m_overworldEvents = ow; +atUint32 ALTTPQuest::oldManFlagCount() const { return (atUint32)m_oldManFlags.size(); } + +void ALTTPQuest::setBombFlag(atUint8 flag) { m_bombFlag = flag; } + +atUint8 ALTTPQuest::bombFlag() const { return m_bombFlag; } + +void ALTTPQuest::setUnknown1(std::vector flags) { m_unknown1 = flags; } + +void ALTTPQuest::setUnknown1(atUint32 id, atUint8 val) { + if (id > m_unknown1.size()) { + atWarning("index out of range"); + return; + } + + m_unknown1[id] = val; } -void ALTTPQuest::setOverworldEvents(ALTTPOverworldEvent* ow, atUint32 id) -{ - m_overworldEvents[id] = ow; +atUint8 ALTTPQuest::unknown1(atUint32 id) { + if (id > m_unknown1.size()) { + atWarning("index out of range"); + return 0; + } + + return m_unknown1[id]; } -std::vector ALTTPQuest::overworldEvents() const -{ - return m_overworldEvents; -} +atUint32 ALTTPQuest::unknown1Count() const { return (atUint32)m_unknown1.size(); } -ALTTPOverworldEvent* ALTTPQuest::overworldEvent(atUint32 id) const -{ - if (id > m_overworldEvents.size() - 1) - { - atWarning("index out of range"); - return nullptr; +void ALTTPQuest::setPlayerName(std::vector playerName) { m_playerName = playerName; } + +void ALTTPQuest::setPlayerName(const std::string& playerName) { + if (playerName == std::string() || playerName.size() > 6) { + atWarning("index out of range"); + return; + } + + m_playerName.clear(); + + for (atUint32 i = 0; i < 6; i++) { + if (i > playerName.size() - 1) { + m_playerName.push_back((atUint16)0xA9); + continue; } - return m_overworldEvents[id]; -} + char c = playerName[i]; -void ALTTPQuest::setInventory(const ALTTPInventory& inv) -{ - m_inventory = inv; -} + if (c >= 'A' && c <= 'P' && c != 'I') { -const ALTTPInventory& ALTTPQuest::inventory() const -{ - return m_inventory; -} - -void ALTTPQuest::setRupeeMax(atUint16 val) -{ - m_rupeeMax = val; -} - -atUint16 ALTTPQuest::rupeeMax() const -{ - return m_rupeeMax; -} - -void ALTTPQuest::setRupeeCurrent(atUint16 val) -{ - m_rupeeCurrent = val; -} - -atUint16 ALTTPQuest::rupeeCurrent() const -{ - return m_rupeeCurrent; -} - -void ALTTPQuest::setCompasses(ALTTPDungeonItemFlags flags) -{ - m_compasses = flags; -} - -ALTTPDungeonItemFlags ALTTPQuest::compasses() const -{ - return m_compasses; -} - -void ALTTPQuest::setBigKeys(ALTTPDungeonItemFlags flags) -{ - m_bigKeys = flags; -} - -ALTTPDungeonItemFlags ALTTPQuest::bigKeys() const -{ - return m_bigKeys; -} - -void ALTTPQuest::setDungeonMaps(ALTTPDungeonItemFlags flags) -{ - m_dungeonMaps = flags; -} - -ALTTPDungeonItemFlags ALTTPQuest::dungeonMaps() const -{ - return m_dungeonMaps; -} - -void ALTTPQuest::setWishingPond(atUint16 val) -{ - m_wishingPond = val; -} - -atUint16 ALTTPQuest::wishingPond() const -{ - return m_wishingPond; -} - -void ALTTPQuest::setHealthMax(atUint8 val) -{ - m_healthMax = val; -} - -atUint8 ALTTPQuest::healthMax() const -{ - return m_healthMax; -} - -void ALTTPQuest::setHealth(atUint8 val) -{ - m_health = val; -} - -atUint8 ALTTPQuest::health() const -{ - return m_health; -} - -void ALTTPQuest::setMagicPower(atUint8 val) -{ - m_magicPower = val; -} - -atUint8 ALTTPQuest::magicPower() const -{ - return m_magicPower; -} - -void ALTTPQuest::setKeys(atUint8 val) -{ - m_keys = val; -} - -atUint8 ALTTPQuest::keys() const -{ - return m_keys; -} - -void ALTTPQuest::setBombUpgrades(atUint8 val) -{ - m_bombUpgrades = val; -} - -atUint8 ALTTPQuest::bombUpgrades() const -{ - return m_bombUpgrades; -} - -void ALTTPQuest::setArrowUpgrades(atUint8 val) -{ - m_arrowUpgrades = val; -} - -atUint8 ALTTPQuest::arrowUpgrades() const -{ - return m_arrowUpgrades; -} - -void ALTTPQuest::setHealthFiller(atUint8 val) -{ - m_heartFiller = val; -} - -atUint8 ALTTPQuest::healthFiller() const -{ - return m_heartFiller; -} -void ALTTPQuest::setMagicFiller(atUint8 val) -{ - m_heartFiller = val; -} - -atUint8 ALTTPQuest::magicFiller() const -{ - return m_heartFiller; -} - -void ALTTPQuest::setPendants(ALTTPPendants val) -{ - m_pendants = val; -} - -ALTTPPendants ALTTPQuest::pendants() const -{ - return m_pendants; -} - -void ALTTPQuest::setBombFiller(atUint8 val) -{ - m_bombFiller = val; -} - -atUint8 ALTTPQuest::bombFiller() const -{ - return m_bombFiller; -} - -void ALTTPQuest::setArrowFiller(atUint8 val) -{ - m_arrowFiller = val; -} - -atUint8 ALTTPQuest::arrowFiller() const -{ - return m_arrowFiller; -} -void ALTTPQuest::setArrows(atUint8 val) -{ - m_arrows = val; -} - -atUint8 ALTTPQuest::arrows() const -{ - return m_arrows; -} - -void ALTTPQuest::setAbilityFlags(ALTTPAbilities val) -{ - m_abilityFlags = val; -} - -ALTTPAbilities ALTTPQuest::abilityFlags() const -{ - return m_abilityFlags; -} - -void ALTTPQuest::setCrystals(ALTTPCrystals val) -{ - m_crystals = val; -} - -ALTTPCrystals ALTTPQuest::crystals() const -{ - return m_crystals; -} - -void ALTTPQuest::setMagicUsage(ALTTPMagicUsage val) -{ - m_magicUsage = val; -} - -ALTTPMagicUsage ALTTPQuest::magicUsage() const -{ - return m_magicUsage; -} - -void ALTTPQuest::setDungeonKeys(std::vector val) -{ - m_dungeonKeys = val; -} - -void ALTTPQuest::setDungeonKeys(atUint32 id, atUint8 val) -{ - if (id > m_dungeonKeys.size() - 1) - { - atWarning("index out of range"); - return; + m_playerName.push_back((atUint16)(c - 'A')); + continue; } - m_dungeonKeys[id] = val; -} - -atUint8 ALTTPQuest::dungeonKeys(atUint32 id) const -{ - if (id > m_dungeonKeys.size() - 1) - { - atWarning("index out of range"); - return 0; + if (c >= 'Q' && c <= 'Z') { + std::cout << std::hex << (atUint16)((c - 'Q') + 0x20) << std::endl; + m_playerName.push_back((atUint16)((c - 'Q') + 0x20)); + continue; } - return m_dungeonKeys[id]; -} - -atUint32 ALTTPQuest::dungeonCount() const -{ - return (atUint32)m_dungeonKeys.size(); -} - - -void ALTTPQuest::setProgressIndicator(ALTTPProgressIndicator val) -{ - m_progressIndicator = val; -} - -ALTTPProgressIndicator ALTTPQuest::progressIndicator() const -{ - return m_progressIndicator; -} - -void ALTTPQuest::setProgressFlags1(ALTTPProgressFlags1 val) -{ - m_progressFlags1 = val; -} - -ALTTPProgressFlags1 ALTTPQuest::progressFlags1() const -{ - return m_progressFlags1; -} - -void ALTTPQuest::setMapIcon(ALTTPMapIcon val) -{ - m_mapIcon = val; -} - -ALTTPMapIcon ALTTPQuest::mapIcon() const -{ - return m_mapIcon; -} - -void ALTTPQuest::setStartLocation(ALTTPStartLocation val) -{ - m_startLocation = val; -} - -ALTTPStartLocation ALTTPQuest::startLocation() const -{ - return m_startLocation; -} - -void ALTTPQuest::setProgressFlags2(ALTTPProgressFlags2 val) -{ - m_progressFlags2 = val; -} - -ALTTPProgressFlags2 ALTTPQuest::progressFlags2() const -{ - return m_progressFlags2; -} - -void ALTTPQuest::setLightDarkWorldIndicator(ALTTPLightDarkWorldIndicator val) -{ - m_lightDarkWorldIndicator = val; -} - -ALTTPLightDarkWorldIndicator ALTTPQuest::lightDarkWorldIndicator() const -{ - return m_lightDarkWorldIndicator; -} - -void ALTTPQuest::setTagAlong(ALTTPTagAlong val) -{ - m_tagAlong = val; -} - -ALTTPTagAlong ALTTPQuest::tagAlong() const -{ - return m_tagAlong; -} - -void ALTTPQuest::setOldManFlags(std::vector flags) -{ - m_oldManFlags = flags; -} - -void ALTTPQuest::setOldManFlag(atUint32 id, atUint8 val) -{ - if (id > m_oldManFlags.size() - 1) - { - atWarning("index out of range"); - return; + if (c >= 'a' && c <= 'f') { + std::cout << std::hex << (atUint16)((c - 'a') + 0x2A) << std::endl; + m_playerName.push_back((atUint16)((c - 'a') + 0x2A)); + continue; } - m_oldManFlags[id] = val; -} + if (c >= 'g' && c <= 'v') { + if (c == 'k') { + m_playerName.push_back(0x42); + continue; + } -atUint8 ALTTPQuest::oldManFlag(atUint32 id) -{ - if (id > m_oldManFlags.size() - 1) - { - atWarning("index out of range"); - return 0; - } - return m_oldManFlags[id]; -} + if (c == 'i') { + m_playerName.push_back(0x44); + continue; + } -atUint32 ALTTPQuest::oldManFlagCount() const -{ - return (atUint32)m_oldManFlags.size(); -} - -void ALTTPQuest::setBombFlag(atUint8 flag) -{ - m_bombFlag = flag; -} - -atUint8 ALTTPQuest::bombFlag() const -{ - return m_bombFlag; -} - -void ALTTPQuest::setUnknown1(std::vector flags) -{ - m_unknown1 = flags; -} - -void ALTTPQuest::setUnknown1(atUint32 id, atUint8 val) -{ - if (id > m_unknown1.size()) - { - atWarning("index out of range"); - return; + m_playerName.push_back((atUint16)((c - 'g') + 0x40)); + continue; } - m_unknown1[id] = val; -} - -atUint8 ALTTPQuest::unknown1(atUint32 id) -{ - if (id > m_unknown1.size()) - { - atWarning("index out of range"); - return 0; + if (c >= 'w' && c <= 'z') { + m_playerName.push_back((atUint16)((c - 'w') + 0x60)); + continue; } - return m_unknown1[id]; -} - -atUint32 ALTTPQuest::unknown1Count() const -{ - return (atUint32)m_unknown1.size(); -} - -void ALTTPQuest::setPlayerName(std::vector playerName) -{ - m_playerName = playerName; -} - -void ALTTPQuest::setPlayerName(const std::string& playerName) -{ - if (playerName == std::string() || playerName.size() > 6) - { - atWarning("index out of range"); - return; + if (c >= '0' && c <= '9') { + m_playerName.push_back((atUint16)((c - '0') + 0x64)); + continue; } - m_playerName.clear(); - - for (atUint32 i = 0; i < 6; i++) - { - if (i > playerName.size() - 1) - { - m_playerName.push_back((atUint16)0xA9); - continue; - } - - char c = playerName[i]; - - if (c >= 'A' && c <= 'P' && c != 'I') - { - - m_playerName.push_back((atUint16)(c - 'A')); - continue; - } - - if (c >= 'Q' && c <= 'Z') - { - std::cout << std::hex << (atUint16)((c - 'Q') + 0x20) << std::endl; - m_playerName.push_back((atUint16)((c - 'Q') + 0x20)); - continue; - } - - if (c >= 'a' && c <= 'f') - { - std::cout << std::hex << (atUint16)((c - 'a') + 0x2A) << std::endl; - m_playerName.push_back((atUint16)((c - 'a') + 0x2A)); - continue; - } - - if (c >= 'g' && c <= 'v') - { - if (c == 'k') - { - m_playerName.push_back(0x42); - continue; - } - - if (c == 'i') - { - m_playerName.push_back(0x44); - continue; - } - - m_playerName.push_back((atUint16)((c - 'g') + 0x40)); - continue; - } - - if (c >= 'w' && c <= 'z') - { - m_playerName.push_back((atUint16)((c - 'w') + 0x60)); - continue; - } - - if (c >= '0' && c <= '9') - { - m_playerName.push_back((atUint16)((c - '0') + 0x64)); - continue; - } - - if (c == '-' || c == '.') - { - m_playerName.push_back((atUint16)(c - '-') + 0x80); - continue; - } - - switch (c) - { - case '?' : - m_playerName.push_back(0x6E); - break; - - case '!' : - m_playerName.push_back(0x6F); - break; - - case ',' : - m_playerName.push_back(0x82); - break; - - case '(' : - m_playerName.push_back(0x85); - break; - - case ')' : - m_playerName.push_back(0x86); - break; - - case 'I' : - m_playerName.push_back(0xAF); - break; - } - } -} - -std::vector ALTTPQuest::playerName() const -{ - return m_playerName; -} - -std::string ALTTPQuest::playerNameToString() const -{ - std::string ret; - - for (atInt16 c : m_playerName) - { - if (c >= 0x00 && c <= 0x0F) - { - ret.push_back((char)('A' + c)); - continue; - } - - if (c >= 0x20 && c <= 0x29) - { - ret.push_back((char)('Q' + (c - 0x20))); - continue; - } - - if (c >= 0x2A && c <= 0x2F) - { - ret.push_back((char)('a' + (c - 0x2A))); - continue; - } - - if (c >= 0x40 && c <= 0x4F) - { - if (c == 0x42) - { - ret.push_back('k'); - continue; - } - - if (c == 0x44) - { - ret.push_back('i'); - continue; - } - - ret.push_back((char)('g' + (c - 0x40))); - } - - if (c >= 0x60 && c <= 0x63) - { - ret.push_back((char)('w' + (c - 0x60))); - continue; - } - - if (c >= 0x64 && c <= 0x6D) - { - ret.push_back((char)('0' + (c - 0x64))); - continue; - } - - if (c == 0x80 || c == 0x81) - { - ret.push_back((char)('-' + (c - 0x80))); - continue; - } - - switch (c) - { - case 0x6E: - ret.push_back('?'); - break; - - case 0x6F: - ret.push_back('!'); - break; - - case 0x82: - ret.push_back(','); - break; - - case 0x85: - ret.push_back('('); - break; - - case 0x86: - ret.push_back(')'); - break; - - case 0xAF: - ret.push_back('I'); - break; - } + if (c == '-' || c == '.') { + m_playerName.push_back((atUint16)(c - '-') + 0x80); + continue; } - return ret; + switch (c) { + case '?': + m_playerName.push_back(0x6E); + break; + + case '!': + m_playerName.push_back(0x6F); + break; + + case ',': + m_playerName.push_back(0x82); + break; + + case '(': + m_playerName.push_back(0x85); + break; + + case ')': + m_playerName.push_back(0x86); + break; + + case 'I': + m_playerName.push_back(0xAF); + break; + } + } } -void ALTTPQuest::setValid(bool val) -{ - m_valid = val; -} +std::vector ALTTPQuest::playerName() const { return m_playerName; } -bool ALTTPQuest::valid() -{ - return m_valid; -} +std::string ALTTPQuest::playerNameToString() const { + std::string ret; -void ALTTPQuest::setDungeonDeathTotals(std::vector val) -{ - m_dungeonDeathTotals = val; -} - -void ALTTPQuest::setDungeonDeathTotal(atUint32 id, atUint16 val) -{ - if (id > m_dungeonDeathTotals.size()) - { - atWarning("index out of range"); - return; + for (atInt16 c : m_playerName) { + if (c >= 0x00 && c <= 0x0F) { + ret.push_back((char)('A' + c)); + continue; } - m_dungeonDeathTotals[id] = val; -} - -atUint16 ALTTPQuest::dungeonDeathTotal(atUint32 id) const -{ - if (id > m_dungeonDeathTotals.size()) - { - atWarning("index out of range"); - return 0; + if (c >= 0x20 && c <= 0x29) { + ret.push_back((char)('Q' + (c - 0x20))); + continue; } - return m_dungeonDeathTotals[id]; + if (c >= 0x2A && c <= 0x2F) { + ret.push_back((char)('a' + (c - 0x2A))); + continue; + } + + if (c >= 0x40 && c <= 0x4F) { + if (c == 0x42) { + ret.push_back('k'); + continue; + } + + if (c == 0x44) { + ret.push_back('i'); + continue; + } + + ret.push_back((char)('g' + (c - 0x40))); + } + + if (c >= 0x60 && c <= 0x63) { + ret.push_back((char)('w' + (c - 0x60))); + continue; + } + + if (c >= 0x64 && c <= 0x6D) { + ret.push_back((char)('0' + (c - 0x64))); + continue; + } + + if (c == 0x80 || c == 0x81) { + ret.push_back((char)('-' + (c - 0x80))); + continue; + } + + switch (c) { + case 0x6E: + ret.push_back('?'); + break; + + case 0x6F: + ret.push_back('!'); + break; + + case 0x82: + ret.push_back(','); + break; + + case 0x85: + ret.push_back('('); + break; + + case 0x86: + ret.push_back(')'); + break; + + case 0xAF: + ret.push_back('I'); + break; + } + } + + return ret; } -atUint16 ALTTPQuest::dungeonDeathTotalCount() const -{ - return (atUint16)m_dungeonDeathTotals.size(); +void ALTTPQuest::setValid(bool val) { m_valid = val; } + +bool ALTTPQuest::valid() { return m_valid; } + +void ALTTPQuest::setDungeonDeathTotals(std::vector val) { m_dungeonDeathTotals = val; } + +void ALTTPQuest::setDungeonDeathTotal(atUint32 id, atUint16 val) { + if (id > m_dungeonDeathTotals.size()) { + atWarning("index out of range"); + return; + } + + m_dungeonDeathTotals[id] = val; } -void ALTTPQuest::setUnknown2(atUint16 val) -{ - m_unknown2 = val; +atUint16 ALTTPQuest::dungeonDeathTotal(atUint32 id) const { + if (id > m_dungeonDeathTotals.size()) { + atWarning("index out of range"); + return 0; + } + + return m_dungeonDeathTotals[id]; } -atUint16 ALTTPQuest::unknown2() const -{ - return m_unknown2; -} +atUint16 ALTTPQuest::dungeonDeathTotalCount() const { return (atUint16)m_dungeonDeathTotals.size(); } -void ALTTPQuest::setDeathSaveCount(atUint16 val) -{ - m_deathSaveCount = val; -} -atUint16 ALTTPQuest::deathSaveCount() const -{ - return m_deathSaveCount; -} +void ALTTPQuest::setUnknown2(atUint16 val) { m_unknown2 = val; } -void ALTTPQuest::setPostGameDeathCounter(atInt16 val) -{ - m_postGameDeathCounter = val; -} +atUint16 ALTTPQuest::unknown2() const { return m_unknown2; } -atInt16 ALTTPQuest::postGameDeathCounter() const -{ - return m_postGameDeathCounter; -} +void ALTTPQuest::setDeathSaveCount(atUint16 val) { m_deathSaveCount = val; } +atUint16 ALTTPQuest::deathSaveCount() const { return m_deathSaveCount; } -void ALTTPQuest::setChecksum(atUint16 checksum) -{ - m_checksum = checksum; -} +void ALTTPQuest::setPostGameDeathCounter(atInt16 val) { m_postGameDeathCounter = val; } -atUint16 ALTTPQuest::checksum() const -{ - return m_checksum; -} +atInt16 ALTTPQuest::postGameDeathCounter() const { return m_postGameDeathCounter; } -} // zelda +void ALTTPQuest::setChecksum(atUint16 checksum) { m_checksum = checksum; } + +atUint16 ALTTPQuest::checksum() const { return m_checksum; } + +} // namespace athena diff --git a/src/athena/Checksums.cpp b/src/athena/Checksums.cpp index 4cd2313..da0bcd8 100644 --- a/src/athena/Checksums.cpp +++ b/src/athena/Checksums.cpp @@ -3,232 +3,182 @@ #include #include -namespace athena::checksums -{ -atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed, atUint64 final) -{ - static const atUint64 crc64Table[256] = - { - 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, - 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, - 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, - 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4, - 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, - 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, - 0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, - 0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, - 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B, - 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, - 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, - 0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, - 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, - 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B, - 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A, - 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, - 0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, - 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645, - 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324, - 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, - 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, - 0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, - 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB, - 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14, - 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, - 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, - 0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, - 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, - 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB, - 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874, - 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, - 0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, - 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78, - 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7, - 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, - 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, - 0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, - 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, - 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329, - 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, - 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, - 0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, - 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, - 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7, - 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149, - 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, - 0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, - 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428, - 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57, - 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, - 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, - 0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, - 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, - 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767, - 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206, - 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, - 0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, - 0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, - 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37, - 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8, - 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, - 0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, - 0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8, - 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507, - }; +namespace athena::checksums { +atUint64 crc64(const atUint8* data, atUint64 length, atUint64 seed, atUint64 final) { + static const atUint64 crc64Table[256] = { + 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x493366450E42ECDF, + 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, + 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, + 0x1C4488F3E8F96ED4, 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, + 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, 0xF45BB4758C645C51, + 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, 0xBD68D2308226B08E, 0xFF9833DB2BCC861D, + 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, + 0x0B6BD3C3DBFD506B, 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, + 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x172F5B3033043EBF, + 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, + 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, + 0x2465CD79455E395B, 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A, + 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, 0xDA050215EA6C212F, + 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, + 0x16D7A787B7FAA0D6, 0x5427466C1E109645, 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, + 0x8F72ECA30CD7A324, 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, + 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, 0xF50B1CAF74CF481F, + 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, + 0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, + 0xA07CF2199274CA14, 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, + 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x84193F60D72AF34F, + 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, + 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, + 0xB753A929A170F4AB, 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874, + 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, 0xAB1721DA49899A7F, + 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, + 0x731B26172EE619EB, 0x31EBC7FC870C2F78, 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, + 0x78D8A1B9894EC3A7, 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, + 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, 0x90C79D3FEDD3F122, + 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, + 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, + 0xC5B073890B687329, 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, + 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0x73B3727A52B393CC, + 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, + 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, + 0x26C49CCCB40811C7, 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149, + 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, 0xCEDBA04AD0952342, + 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, + 0x020905D88D03A2BB, 0x40F9E43324E99428, 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, + 0xEBEEC5E96D600E57, 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, + 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, 0xF7AA4D1A85996083, + 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, + 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, + 0xC4E0DB53F3C36767, 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206, + 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, 0xE085162AB69D5E3C, + 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, 0xA9B6706FB8DFB2E3, 0xEB46918411358470, + 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, + 0xB5F2F89C5026DC37, 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8, + 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, 0xCF8B0890283E370C, + 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, 0x14DEA25F3AF9026D, 0x562E43B4931334FE, + 0x913F6188692D6F4B, 0xD3CF8063C0C759D8, 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, + 0x9AFCE626CE85B507, + }; - if (!data) - return seed; + if (!data) + return seed; - atUint64 checksum = seed; - int pos = 0; + atUint64 checksum = seed; + int pos = 0; - while (length--) - checksum = crc64Table[((checksum >> 56) ^ data[pos++]) & 0xff] ^ (checksum << 8); + while (length--) + checksum = crc64Table[((checksum >> 56) ^ data[pos++]) & 0xff] ^ (checksum << 8); - return checksum ^ final; + return checksum ^ final; } -atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed, atUint32 final) -{ - static const atUint32 crc32Table[256] = - { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D - }; +atUint32 crc32(const atUint8* data, atUint64 length, atUint32 seed, atUint32 final) { + static const atUint32 crc32Table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}; - if (!data) - return seed; + if (!data) + return seed; - atUint32 checksum = seed; - int pos = 0; + atUint32 checksum = seed; + int pos = 0; - while (length--) - checksum = (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ data[pos++]]; + while (length--) + checksum = (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ data[pos++]]; - return checksum ^ final; + return checksum ^ final; } -atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint16 final) -{ - static const atUint16 crc16CCITTTable [256] = - { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, - 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, - 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, - 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, - 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, - 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, - 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, - 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, - 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, - 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, - 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, - 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, - 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, - 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, - 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, - 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, - 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, - 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, - 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, - 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, - 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, - 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, - 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, - 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, - 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, - 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 - }; +atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint16 final) { + static const atUint16 crc16CCITTTable[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, + 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, + 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, + 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, + 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, + 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, + 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, + 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, + 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, + 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, + 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, + 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, + 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, + 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; - atUint16 checksum = seed; - int pos = 0; + atUint16 checksum = seed; + int pos = 0; - while (length--) - checksum = crc16CCITTTable[(data[pos++] ^ (checksum >> 8)) & 0xFF] ^ (checksum << 8); + while (length--) + checksum = crc16CCITTTable[(data[pos++] ^ (checksum >> 8)) & 0xFF] ^ (checksum << 8); - return checksum ^ final; + return checksum ^ final; } -atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) -{ - if (data) - return seed; +atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) { + if (data) + return seed; - static const atUint16 crc16Table[256] = - { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 - }; + static const atUint16 crc16Table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, + 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, + 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, + 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, + 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, + 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, + 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, + 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, + 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, + 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, + 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, + 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, + 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, + 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, + 0x4100, 0x81C1, 0x8081, 0x4040}; - atInt32 pos = 0; - atUint16 checksum = seed; + atInt32 pos = 0; + atUint16 checksum = seed; - while (length--) - checksum = (crc16Table[(checksum ^ data[pos++]) & 0xFF] ^ (checksum >> 8)); + while (length--) + checksum = (crc16Table[(checksum ^ data[pos++]) & 0xFF] ^ (checksum >> 8)); - return checksum ^ final; + return checksum ^ final; } -} // Checksums +} // namespace athena::checksums diff --git a/src/athena/Compression.cpp b/src/athena/Compression.cpp index 54380e2..2e09577 100644 --- a/src/athena/Compression.cpp +++ b/src/athena/Compression.cpp @@ -5,351 +5,311 @@ #include "LZ77/LZType10.hpp" #include "LZ77/LZType11.hpp" -namespace athena::io::Compression -{ +namespace athena::io::Compression { -atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) -{ - z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - strm.total_in = strm.avail_in = srcLen; - strm.total_out = strm.avail_out = dstLen; - strm.next_in = (Bytef*) src; - strm.next_out = (Bytef*) dst; +atInt32 decompressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) { + z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + strm.total_in = strm.avail_in = srcLen; + strm.total_out = strm.avail_out = dstLen; + strm.next_in = (Bytef*)src; + strm.next_out = (Bytef*)dst; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; - atInt32 err = -1; - atInt32 ret = -1; + atInt32 err = -1; + atInt32 ret = -1; - err = inflateInit(&strm); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib + err = inflateInit(&strm); // 15 window bits, and the +32 tells zlib to to detect if using gzip or zlib - if (err == Z_OK) - { - err = inflate(&strm, Z_FINISH); + if (err == Z_OK) { + err = inflate(&strm, Z_FINISH); - if (err == Z_STREAM_END) - ret = strm.total_out; - else - { - inflateEnd(&strm); - return err; - } + if (err == Z_STREAM_END) + ret = strm.total_out; + else { + inflateEnd(&strm); + return err; } - else - { - inflateEnd(&strm); - return err; - } - + } else { inflateEnd(&strm); + return err; + } - return ret; + inflateEnd(&strm); + + return ret; } -atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) -{ - z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - strm.total_in = strm.avail_in = srcLen; - strm.total_out = strm.avail_out = dstLen; - strm.next_in = (Bytef*) src; - strm.next_out = (Bytef*) dst; +atInt32 compressZlib(const atUint8* src, atUint32 srcLen, atUint8* dst, atUint32 dstLen) { + z_stream strm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + strm.total_in = strm.avail_in = srcLen; + strm.total_out = strm.avail_out = dstLen; + strm.next_in = (Bytef*)src; + strm.next_out = (Bytef*)dst; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; - atInt32 err = -1; - atInt32 ret = -1; + atInt32 err = -1; + atInt32 ret = -1; - err = deflateInit(&strm, Z_BEST_COMPRESSION); + err = deflateInit(&strm, Z_BEST_COMPRESSION); - if (err == Z_OK) - { - err = deflate(&strm, Z_FINISH); + if (err == Z_OK) { + err = deflate(&strm, Z_FINISH); - if (err == Z_STREAM_END) - ret = strm.total_out; - else - { - deflateEnd(&strm); - return err; - } + if (err == Z_STREAM_END) + ret = strm.total_out; + else { + deflateEnd(&strm); + return err; } - else - { - deflateEnd(&strm); - return err; - } - + } else { deflateEnd(&strm); + return err; + } - return ret; + deflateEnd(&strm); + + return ret; } -atInt32 decompressLZO(const atUint8* source, const atInt32 sourceSize, atUint8* dst, atInt32& dstSize) -{ - int srcSize = sourceSize; - lzo_uint size = dstSize; - int result = lzo1x_decompress_safe(source, srcSize, dst, &size, NULL); - dstSize -= (atInt32)size; +atInt32 decompressLZO(const atUint8* source, const atInt32 sourceSize, atUint8* dst, atInt32& dstSize) { + int srcSize = sourceSize; + lzo_uint size = dstSize; + int result = lzo1x_decompress_safe(source, srcSize, dst, &size, NULL); + dstSize -= (atInt32)size; - return result; + return result; } -//src points to the yaz0 source data (to the "real" source data, not at the header!) -//dst points to a buffer uncompressedSize bytes large (you get uncompressedSize from -//the second 4 bytes in the Yaz0 header). -atUint32 yaz0Decode(const atUint8* src, atUint8* dst, atUint32 uncompressedSize) -{ - atUint32 srcPlace = 0, dstPlace = 0; //current read/write positions +// src points to the yaz0 source data (to the "real" source data, not at the header!) +// dst points to a buffer uncompressedSize bytes large (you get uncompressedSize from +// the second 4 bytes in the Yaz0 header). +atUint32 yaz0Decode(const atUint8* src, atUint8* dst, atUint32 uncompressedSize) { + atUint32 srcPlace = 0, dstPlace = 0; // current read/write positions - atInt32 validBitCount = 0; //number of valid bits left in "code" byte - atUint8 currCodeByte; + atInt32 validBitCount = 0; // number of valid bits left in "code" byte + atUint8 currCodeByte; - while (dstPlace < uncompressedSize) - { - //read new "code" byte if the current one is used up - if (validBitCount == 0) - { - currCodeByte = src[srcPlace]; - ++srcPlace; - validBitCount = 8; - } - - if ((currCodeByte & 0x80) != 0) - { - //straight copy - dst[dstPlace] = src[srcPlace]; - dstPlace++; - srcPlace++; - } - else - { - //RLE part - atUint8 byte1 = src[srcPlace]; - atUint8 byte2 = src[srcPlace + 1]; - srcPlace += 2; - - atUint32 dist = ((byte1 & 0xF) << 8) | byte2; - atUint32 copySource = dstPlace - (dist + 1); - - atUint32 numBytes = byte1 >> 4; - - if (numBytes == 0) - { - numBytes = src[srcPlace] + 0x12; - srcPlace++; - } - else - numBytes += 2; - - //copy run - for (atUint32 i = 0; i < numBytes; ++i) - { - dst[dstPlace] = dst[copySource]; - copySource++; - dstPlace++; - } - } - - //use next bit from "code" byte - currCodeByte <<= 1; - validBitCount -= 1; + while (dstPlace < uncompressedSize) { + // read new "code" byte if the current one is used up + if (validBitCount == 0) { + currCodeByte = src[srcPlace]; + ++srcPlace; + validBitCount = 8; } - return dstPlace; + if ((currCodeByte & 0x80) != 0) { + // straight copy + dst[dstPlace] = src[srcPlace]; + dstPlace++; + srcPlace++; + } else { + // RLE part + atUint8 byte1 = src[srcPlace]; + atUint8 byte2 = src[srcPlace + 1]; + srcPlace += 2; + + atUint32 dist = ((byte1 & 0xF) << 8) | byte2; + atUint32 copySource = dstPlace - (dist + 1); + + atUint32 numBytes = byte1 >> 4; + + if (numBytes == 0) { + numBytes = src[srcPlace] + 0x12; + srcPlace++; + } else + numBytes += 2; + + // copy run + for (atUint32 i = 0; i < numBytes; ++i) { + dst[dstPlace] = dst[copySource]; + copySource++; + dstPlace++; + } + } + + // use next bit from "code" byte + currCodeByte <<= 1; + validBitCount -= 1; + } + + return dstPlace; } // Yaz0 encode -typedef struct -{ - atUint32 srcPos, dstPos; +typedef struct { + atUint32 srcPos, dstPos; } yaz0_Ret; atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos); atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos); -atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data) -{ - yaz0_Ret r = { 0, 0 }; - atInt32 pos = 0; - atUint8 dst[24]; // 8 codes * 3 bytes maximum - atUint32 dstSize = 0; - atUint32 i; +atUint32 yaz0Encode(const atUint8* src, atUint32 srcSize, atUint8* data) { + yaz0_Ret r = {0, 0}; + atInt32 pos = 0; + atUint8 dst[24]; // 8 codes * 3 bytes maximum + atUint32 dstSize = 0; + atUint32 i; - atUint32 validBitCount = 0; //number of valid bits left in "code" byte - atUint8 currCodeByte = 0; + atUint32 validBitCount = 0; // number of valid bits left in "code" byte + atUint8 currCodeByte = 0; - while (r.srcPos < srcSize) - { - atUint32 numBytes; - atUint32 matchPos; - numBytes = nintendoEnc(src, srcSize, r.srcPos, &matchPos); + while (r.srcPos < srcSize) { + atUint32 numBytes; + atUint32 matchPos; + numBytes = nintendoEnc(src, srcSize, r.srcPos, &matchPos); - if (numBytes < 3) - { - //straight copy - dst[r.dstPos] = src[r.srcPos]; - r.dstPos++; - r.srcPos++; - //set flag for straight copy - currCodeByte |= (0x80 >> validBitCount); - } - else - { - //RLE part - atUint32 dist = r.srcPos - matchPos - 1; - atUint8 byte1, byte2, byte3; + if (numBytes < 3) { + // straight copy + dst[r.dstPos] = src[r.srcPos]; + r.dstPos++; + r.srcPos++; + // set flag for straight copy + currCodeByte |= (0x80 >> validBitCount); + } else { + // RLE part + atUint32 dist = r.srcPos - matchPos - 1; + atUint8 byte1, byte2, byte3; - if (numBytes >= 0x12) // 3 byte encoding - { - byte1 = 0 | (dist >> 8); - byte2 = dist & 0xff; - dst[r.dstPos++] = byte1; - dst[r.dstPos++] = byte2; + if (numBytes >= 0x12) // 3 byte encoding + { + byte1 = 0 | (dist >> 8); + byte2 = dist & 0xff; + dst[r.dstPos++] = byte1; + dst[r.dstPos++] = byte2; - // maximum runlength for 3 byte encoding - if (numBytes > 0xff + 0x12) - numBytes = 0xff + 0x12; + // maximum runlength for 3 byte encoding + if (numBytes > 0xff + 0x12) + numBytes = 0xff + 0x12; - byte3 = numBytes - 0x12; - dst[r.dstPos++] = byte3; - } - else // 2 byte encoding - { - byte1 = ((numBytes - 2) << 4) | (dist >> 8); - byte2 = dist & 0xff; - dst[r.dstPos++] = byte1; - dst[r.dstPos++] = byte2; - } + byte3 = numBytes - 0x12; + dst[r.dstPos++] = byte3; + } else // 2 byte encoding + { + byte1 = ((numBytes - 2) << 4) | (dist >> 8); + byte2 = dist & 0xff; + dst[r.dstPos++] = byte1; + dst[r.dstPos++] = byte2; + } - r.srcPos += numBytes; - } - - validBitCount++; - - //write eight codes - if (validBitCount == 8) - { - data[pos] = currCodeByte; - pos++; - - for (i = 0; i 0) - { - data[pos] = currCodeByte; - pos++; + validBitCount++; - for (i = 0; i 0) { + data[pos] = currCodeByte; + pos++; + + for (i = 0; i < /*=*/r.dstPos; pos++, i++) + data[pos] = dst[i]; + + dstSize += r.dstPos + 1; + + currCodeByte = 0; + validBitCount = 0; + r.dstPos = 0; + } + + return dstSize; } // a lookahead encoding scheme for ngc Yaz0 -atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) -{ - atUint32 numBytes = 1; - static atUint32 numBytes1; - static atUint32 matchPos; - static atInt32 prevFlag = 0; +atUint32 nintendoEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) { + atUint32 numBytes = 1; + static atUint32 numBytes1; + static atUint32 matchPos; + static atInt32 prevFlag = 0; - // if prevFlag is set, it means that the previous position was determined by look-ahead try. - // so just use it. this is not the best optimization, but nintendo's choice for speed. - if (prevFlag == 1) - { - *pMatchPos = matchPos; - prevFlag = 0; - return numBytes1; - } - - prevFlag = 0; - numBytes = simpleEnc(src, size, pos, &matchPos); + // if prevFlag is set, it means that the previous position was determined by look-ahead try. + // so just use it. this is not the best optimization, but nintendo's choice for speed. + if (prevFlag == 1) { *pMatchPos = matchPos; + prevFlag = 0; + return numBytes1; + } - // if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding - if (numBytes >= 3) - { - numBytes1 = simpleEnc(src, size, pos + 1, &matchPos); + prevFlag = 0; + numBytes = simpleEnc(src, size, pos, &matchPos); + *pMatchPos = matchPos; - // if the next position encoding is +2 longer than current position, choose it. - // this does not guarantee the best optimization, but fairly good optimization with speed. - if (numBytes1 >= numBytes + 2) - { - numBytes = 1; - prevFlag = 1; - } + // if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding + if (numBytes >= 3) { + numBytes1 = simpleEnc(src, size, pos + 1, &matchPos); + + // if the next position encoding is +2 longer than current position, choose it. + // this does not guarantee the best optimization, but fairly good optimization with speed. + if (numBytes1 >= numBytes + 2) { + numBytes = 1; + prevFlag = 1; } + } - return numBytes; + return numBytes; } // simple and straight encoding scheme for Yaz0 -atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) -{ - int startPos = pos - 0x1000, j, i; - atUint32 numBytes = 1; - atUint32 matchPos = 0; +atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMatchPos) { + int startPos = pos - 0x1000, j, i; + atUint32 numBytes = 1; + atUint32 matchPos = 0; - if (startPos < 0) - startPos = 0; + if (startPos < 0) + startPos = 0; - for (i = startPos; i < pos; i++) - { - for (j = 0; j < size - pos; j++) - { - if (src[i + j] != src[j + pos]) - break; - } - - if ((atUint32)j > numBytes) - { - numBytes = j; - matchPos = i; - } + for (i = startPos; i < pos; i++) { + for (j = 0; j < size - pos; j++) { + if (src[i + j] != src[j + pos]) + break; } - *pMatchPos = matchPos; + if ((atUint32)j > numBytes) { + numBytes = j; + matchPos = i; + } + } - if (numBytes == 2) - numBytes = 1; + *pMatchPos = matchPos; - return numBytes; + if (numBytes == 2) + numBytes = 1; + + return numBytes; } -atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) -{ - if (*(atUint8*)src == 0x11) - return LZType11().decompress(src, dst, srcLen); +atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) { + if (*(atUint8*)src == 0x11) + return LZType11().decompress(src, dst, srcLen); - return LZType10(2).decompress(src, dst, srcLen); + return LZType10(2).decompress(src, dst, srcLen); } -atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended) -{ - if (extended) - return LZType11().compress(src, dst, srcLen); +atUint32 compressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst, bool extended) { + if (extended) + return LZType11().compress(src, dst, srcLen); - return LZType10(2).compress(src, dst, srcLen); + return LZType10(2).compress(src, dst, srcLen); } -} // Compression +} // namespace athena::io::Compression diff --git a/src/athena/DNAYaml.cpp b/src/athena/DNAYaml.cpp index 7c75881..7c2f7d7 100644 --- a/src/athena/DNAYaml.cpp +++ b/src/athena/DNAYaml.cpp @@ -1,664 +1,559 @@ #include "athena/DNAYaml.hpp" -namespace athena::io -{ +namespace athena::io { template <> -bool NodeToVal(const YAMLNode* node) -{ - char firstCh = tolower(node->m_scalarString[0]); - if (firstCh == 't') - return true; - else if (firstCh == 'f') - return false; - else if (isdigit(firstCh) && firstCh != 0) - return true; +bool NodeToVal(const YAMLNode* node) { + char firstCh = tolower(node->m_scalarString[0]); + if (firstCh == 't') + return true; + else if (firstCh == 'f') return false; + else if (isdigit(firstCh) && firstCh != 0) + return true; + return false; } -std::unique_ptr ValToNode(bool val) -{ - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = val?"True":"False"; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(bool val) { + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = val ? "True" : "False"; + return std::unique_ptr(ret); } template <> -atInt8 NodeToVal(const YAMLNode* node) -{ - return strtol(node->m_scalarString.c_str(), NULL, 0); +atInt8 NodeToVal(const YAMLNode* node) { + return strtol(node->m_scalarString.c_str(), NULL, 0); } -std::unique_ptr ValToNode(atInt8 val) -{ - char str[32]; - snprintf(str, 32, "%d", int(val)); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atInt8 val) { + char str[32]; + snprintf(str, 32, "%d", int(val)); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atUint8 NodeToVal(const YAMLNode* node) -{ - return strtoul(node->m_scalarString.c_str(), NULL, 0); +atUint8 NodeToVal(const YAMLNode* node) { + return strtoul(node->m_scalarString.c_str(), NULL, 0); } -std::unique_ptr ValToNode(atUint8 val) -{ - char str[32]; - snprintf(str, 32, "0x%02X", val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atUint8 val) { + char str[32]; + snprintf(str, 32, "0x%02X", val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atInt16 NodeToVal(const YAMLNode* node) -{ - return strtol(node->m_scalarString.c_str(), NULL, 0); +atInt16 NodeToVal(const YAMLNode* node) { + return strtol(node->m_scalarString.c_str(), NULL, 0); } -std::unique_ptr ValToNode(atInt16 val) -{ - char str[32]; - snprintf(str, 32, "%d", int(val)); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atInt16 val) { + char str[32]; + snprintf(str, 32, "%d", int(val)); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atUint16 NodeToVal(const YAMLNode* node) -{ - return strtoul(node->m_scalarString.c_str(), NULL, 0); +atUint16 NodeToVal(const YAMLNode* node) { + return strtoul(node->m_scalarString.c_str(), NULL, 0); } -std::unique_ptr ValToNode(atUint16 val) -{ - char str[32]; - snprintf(str, 32, "0x%04X", val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atUint16 val) { + char str[32]; + snprintf(str, 32, "0x%04X", val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atInt32 NodeToVal(const YAMLNode* node) -{ - return strtol(node->m_scalarString.c_str(), NULL, 0); +atInt32 NodeToVal(const YAMLNode* node) { + return strtol(node->m_scalarString.c_str(), NULL, 0); } -std::unique_ptr ValToNode(atInt32 val) -{ - char str[32]; - snprintf(str, 32, "%d", int(val)); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atInt32 val) { + char str[32]; + snprintf(str, 32, "%d", int(val)); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atUint32 NodeToVal(const YAMLNode* node) -{ - return strtoul(node->m_scalarString.c_str(), NULL, 0); +atUint32 NodeToVal(const YAMLNode* node) { + return strtoul(node->m_scalarString.c_str(), NULL, 0); } -std::unique_ptr ValToNode(atUint32 val) -{ - char str[32]; - snprintf(str, 32, "0x%08X", val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atUint32 val) { + char str[32]; + snprintf(str, 32, "0x%08X", val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atInt64 NodeToVal(const YAMLNode* node) -{ +atInt64 NodeToVal(const YAMLNode* node) { #if _WIN32 - return _strtoi64(node->m_scalarString.c_str(), NULL, 0); + return _strtoi64(node->m_scalarString.c_str(), NULL, 0); #else - return strtoq(node->m_scalarString.c_str(), NULL, 0); + return strtoq(node->m_scalarString.c_str(), NULL, 0); #endif } -std::unique_ptr ValToNode(atInt64 val) -{ - char str[32]; - snprintf(str, 32, "%" PRId64, val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atInt64 val) { + char str[32]; + snprintf(str, 32, "%" PRId64, val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -atUint64 NodeToVal(const YAMLNode* node) -{ +atUint64 NodeToVal(const YAMLNode* node) { #if _WIN32 - return _strtoui64(node->m_scalarString.c_str(), NULL, 0); + return _strtoui64(node->m_scalarString.c_str(), NULL, 0); #else - return strtouq(node->m_scalarString.c_str(), NULL, 0); + return strtouq(node->m_scalarString.c_str(), NULL, 0); #endif } -std::unique_ptr ValToNode(atUint64 val) -{ - char str[32]; - snprintf(str, 32, "0x%016" PRIX64, val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(atUint64 val) { + char str[32]; + snprintf(str, 32, "0x%016" PRIX64, val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -float NodeToVal(const YAMLNode* node) -{ - return strtof(node->m_scalarString.c_str(), NULL); +float NodeToVal(const YAMLNode* node) { + return strtof(node->m_scalarString.c_str(), NULL); } -std::unique_ptr ValToNode(float val) -{ - char str[64]; - snprintf(str, 64, "%f", val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(float val) { + char str[64]; + snprintf(str, 64, "%f", val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template <> -double NodeToVal(const YAMLNode* node) -{ - return strtod(node->m_scalarString.c_str(), NULL); +double NodeToVal(const YAMLNode* node) { + return strtod(node->m_scalarString.c_str(), NULL); } -std::unique_ptr ValToNode(double val) -{ - char str[64]; - snprintf(str, 64, "%f", val); - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = str; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(double val) { + char str[64]; + snprintf(str, 64, "%f", val); + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = str; + return std::unique_ptr(ret); } template -RETURNTYPE NodeToVec(const YAMLNode* node) -{ - constexpr bool isDouble = std::is_same::value || - std::is_same::value || - std::is_same::value; - RETURNTYPE retval = {}; - auto it = node->m_seqChildren.begin(); - simd_values> f; - for (size_t i=0; - i<4 && it != node->m_seqChildren.end(); - ++i, ++it) - { - YAMLNode* snode = it->get(); - if (snode->m_type == YAML_SCALAR_NODE) - { - if (isDouble) - f[i] = NodeToVal(snode); - else - f[i] = NodeToVal(snode); - } - else - f[i] = 0.0; - } - retval.simd.copy_from(f); - return retval; +RETURNTYPE NodeToVec(const YAMLNode* node) { + constexpr bool isDouble = std::is_same::value || std::is_same::value || + std::is_same::value; + RETURNTYPE retval = {}; + auto it = node->m_seqChildren.begin(); + simd_values> f; + for (size_t i = 0; i < 4 && it != node->m_seqChildren.end(); ++i, ++it) { + YAMLNode* snode = it->get(); + if (snode->m_type == YAML_SCALAR_NODE) { + if (isDouble) + f[i] = NodeToVal(snode); + else + f[i] = NodeToVal(snode); + } else + f[i] = 0.0; + } + retval.simd.copy_from(f); + return retval; } template <> -atVec2f NodeToVal(const YAMLNode* node) -{ - return NodeToVec(node); +atVec2f NodeToVal(const YAMLNode* node) { + return NodeToVec(node); } -std::unique_ptr ValToNode(const atVec2f& val) -{ - YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(2); - simd_floats f(val.simd); - for (size_t i=0 ; i<2 ; ++i) - { - char str[64]; - snprintf(str, 64, "%f", f[i]); - YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); - comp->m_scalarString = str; - ret->m_seqChildren.emplace_back(comp); - } - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const atVec2f& val) { + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(2); + simd_floats f(val.simd); + for (size_t i = 0; i < 2; ++i) { + char str[64]; + snprintf(str, 64, "%f", f[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); } template <> -atVec3f NodeToVal(const YAMLNode* node) -{ - return NodeToVec(node); +atVec3f NodeToVal(const YAMLNode* node) { + return NodeToVec(node); } -std::unique_ptr ValToNode(const atVec3f& val) -{ - YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(3); - simd_floats f(val.simd); - for (size_t i=0 ; i<3 ; ++i) - { - char str[64]; - snprintf(str, 64, "%f", f[i]); - YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); - comp->m_scalarString = str; - ret->m_seqChildren.emplace_back(comp); - } - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const atVec3f& val) { + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(3); + simd_floats f(val.simd); + for (size_t i = 0; i < 3; ++i) { + char str[64]; + snprintf(str, 64, "%f", f[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); } template <> -atVec4f NodeToVal(const YAMLNode* node) -{ - return NodeToVec(node); +atVec4f NodeToVal(const YAMLNode* node) { + return NodeToVec(node); } -std::unique_ptr ValToNode(const atVec4f& val) -{ - YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(4); - simd_floats f(val.simd); - for (size_t i=0 ; i<4 ; ++i) - { - char str[64]; - snprintf(str, 64, "%f", f[i]); - YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); - comp->m_scalarString = str; - ret->m_seqChildren.emplace_back(comp); - } - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const atVec4f& val) { + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(4); + simd_floats f(val.simd); + for (size_t i = 0; i < 4; ++i) { + char str[64]; + snprintf(str, 64, "%f", f[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); } template <> -atVec2d NodeToVal(const YAMLNode* node) -{ - return NodeToVec(node); +atVec2d NodeToVal(const YAMLNode* node) { + return NodeToVec(node); } -std::unique_ptr ValToNode(const atVec2d& val) -{ - YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(2); - simd_doubles f(val.simd); - for (size_t i=0 ; i<2 ; ++i) - { - char str[64]; - snprintf(str, 64, "%f", f[i]); - YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); - comp->m_scalarString = str; - ret->m_seqChildren.emplace_back(comp); - } - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const atVec2d& val) { + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(2); + simd_doubles f(val.simd); + for (size_t i = 0; i < 2; ++i) { + char str[64]; + snprintf(str, 64, "%f", f[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); } template <> -atVec3d NodeToVal(const YAMLNode* node) -{ - return NodeToVec(node); +atVec3d NodeToVal(const YAMLNode* node) { + return NodeToVec(node); } -std::unique_ptr ValToNode(const atVec3d& val) -{ - YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(3); - simd_doubles f(val.simd); - for (size_t i=0 ; i<3 ; ++i) - { - char str[64]; - snprintf(str, 64, "%f", f[i]); - YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); - comp->m_scalarString = str; - ret->m_seqChildren.emplace_back(comp); - } - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const atVec3d& val) { + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(3); + simd_doubles f(val.simd); + for (size_t i = 0; i < 3; ++i) { + char str[64]; + snprintf(str, 64, "%f", f[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); } template <> -atVec4d NodeToVal(const YAMLNode* node) -{ - return NodeToVec(node); +atVec4d NodeToVal(const YAMLNode* node) { + return NodeToVec(node); } -std::unique_ptr ValToNode(const atVec4d& val) -{ - YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(4); - simd_doubles f(val.simd); - for (size_t i=0 ; i<4 ; ++i) - { - char str[64]; - snprintf(str, 64, "%f", f[i]); - YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); - comp->m_scalarString = str; - ret->m_seqChildren.emplace_back(comp); - } - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const atVec4d& val) { + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(4); + simd_doubles f(val.simd); + for (size_t i = 0; i < 4; ++i) { + char str[64]; + snprintf(str, 64, "%f", f[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); } template <> -std::unique_ptr NodeToVal(const YAMLNode* node) -{ - return base64_decode(node->m_scalarString); +std::unique_ptr NodeToVal(const YAMLNode* node) { + return base64_decode(node->m_scalarString); } -std::unique_ptr ValToNode(const std::unique_ptr& val, size_t byteCount) -{ - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - if (val) - ret->m_scalarString = base64_encode(val.get(), byteCount); - return std::unique_ptr(ret); +std::unique_ptr ValToNode(const std::unique_ptr& val, size_t byteCount) { + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + if (val) + ret->m_scalarString = base64_encode(val.get(), byteCount); + return std::unique_ptr(ret); } template <> -std::string NodeToVal(const YAMLNode* node) -{ - return node->m_scalarString; +std::string NodeToVal(const YAMLNode* node) { + return node->m_scalarString; } -std::unique_ptr ValToNode(std::string_view val) -{ - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString = val; - return std::unique_ptr(ret); +std::unique_ptr ValToNode(std::string_view val) { + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString = val; + return std::unique_ptr(ret); } template <> -std::wstring NodeToVal(const YAMLNode* node) -{ - std::wstring retval; - retval.reserve(node->m_scalarString.length()); - const utf8proc_uint8_t* buf = reinterpret_cast(node->m_scalarString.c_str()); - while (*buf) - { - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) - { - atWarning("invalid UTF-8 character while decoding"); - return retval; - } - buf += len; - retval += wchar_t(wc); +std::wstring NodeToVal(const YAMLNode* node) { + std::wstring retval; + retval.reserve(node->m_scalarString.length()); + const utf8proc_uint8_t* buf = reinterpret_cast(node->m_scalarString.c_str()); + while (*buf) { + utf8proc_int32_t wc; + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atWarning("invalid UTF-8 character while decoding"); + return retval; } - return retval; + buf += len; + retval += wchar_t(wc); + } + return retval; } -std::unique_ptr ValToNode(std::wstring_view val) -{ - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString.reserve(val.length()); - for (wchar_t ch : val) - { - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); - if (c < 0) - { - atWarning("invalid UTF-8 character while encoding"); - return std::unique_ptr(ret); - } - ret->m_scalarString.append(reinterpret_cast(mb), c); +std::unique_ptr ValToNode(std::wstring_view val) { + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString.reserve(val.length()); + for (wchar_t ch : val) { + utf8proc_uint8_t mb[4]; + utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); + if (c < 0) { + atWarning("invalid UTF-8 character while encoding"); + return std::unique_ptr(ret); } - return std::unique_ptr(ret); + ret->m_scalarString.append(reinterpret_cast(mb), c); + } + return std::unique_ptr(ret); } -std::unique_ptr ValToNode(std::u16string_view val) -{ - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString.reserve(val.length()); - for (char16_t ch : val) - { - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); - if (c < 0) - { - atWarning("invalid UTF-8 character while encoding"); - return std::unique_ptr(ret); - } - ret->m_scalarString.append(reinterpret_cast(mb), c); +std::unique_ptr ValToNode(std::u16string_view val) { + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString.reserve(val.length()); + for (char16_t ch : val) { + utf8proc_uint8_t mb[4]; + utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); + if (c < 0) { + atWarning("invalid UTF-8 character while encoding"); + return std::unique_ptr(ret); } - return std::unique_ptr(ret); + ret->m_scalarString.append(reinterpret_cast(mb), c); + } + return std::unique_ptr(ret); } -std::unique_ptr ValToNode(std::u32string_view val) -{ - YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); - ret->m_scalarString.reserve(val.length()); - for (char32_t ch : val) - { - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); - if (c < 0) - { - atWarning("invalid UTF-8 character while encoding"); - return std::unique_ptr(ret); - } - ret->m_scalarString.append(reinterpret_cast(mb), c); +std::unique_ptr ValToNode(std::u32string_view val) { + YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); + ret->m_scalarString.reserve(val.length()); + for (char32_t ch : val) { + utf8proc_uint8_t mb[4]; + utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); + if (c < 0) { + atWarning("invalid UTF-8 character while encoding"); + return std::unique_ptr(ret); } - return std::unique_ptr(ret); + ret->m_scalarString.append(reinterpret_cast(mb), c); + } + return std::unique_ptr(ret); } -static const char* ErrorString(yaml_error_type_t errt) -{ - switch (errt) - { - case YAML_NO_ERROR: - return "No Error"; - case YAML_MEMORY_ERROR: - return "Memory Error"; - case YAML_READER_ERROR: - return "Reader Error"; - case YAML_SCANNER_ERROR: - return "Scanner Error"; - case YAML_PARSER_ERROR: - return "Parser Error"; - case YAML_COMPOSER_ERROR: - return "Composer Error"; - case YAML_WRITER_ERROR: - return "Writer Error"; - case YAML_EMITTER_ERROR: - return "Emitter Error"; - } - return "Unknown Error"; +static const char* ErrorString(yaml_error_type_t errt) { + switch (errt) { + case YAML_NO_ERROR: + return "No Error"; + case YAML_MEMORY_ERROR: + return "Memory Error"; + case YAML_READER_ERROR: + return "Reader Error"; + case YAML_SCANNER_ERROR: + return "Scanner Error"; + case YAML_PARSER_ERROR: + return "Parser Error"; + case YAML_COMPOSER_ERROR: + return "Composer Error"; + case YAML_WRITER_ERROR: + return "Writer Error"; + case YAML_EMITTER_ERROR: + return "Emitter Error"; + } + return "Unknown Error"; } -void HandleYAMLParserError(yaml_parser_t* parser) -{ - atError("YAML error: %s: %s", ErrorString(parser->error), parser->problem?parser->problem:""); +void HandleYAMLParserError(yaml_parser_t* parser) { + atError("YAML error: %s: %s", ErrorString(parser->error), parser->problem ? parser->problem : ""); } -void HandleYAMLEmitterError(yaml_emitter_t* emitter) -{ - atError("YAML error: %s: %s", ErrorString(emitter->error), emitter->problem?emitter->problem:""); +void HandleYAMLEmitterError(yaml_emitter_t* emitter) { + atError("YAML error: %s: %s", ErrorString(emitter->error), emitter->problem ? emitter->problem : ""); } -int YAMLStdStringReader(YAMLStdStringViewReaderState* reader, - unsigned char* buffer, size_t size, size_t* size_read) -{ - size_t diff = reader->end - reader->begin; - if (!diff) - { - *size_read = 0; - } - else if (diff < size) - { - memcpy(buffer, &*reader->begin, diff); - *size_read = diff; - } - else - { - memcpy(buffer, &*reader->begin, size); - *size_read = size; - } - return 1; +int YAMLStdStringReader(YAMLStdStringViewReaderState* reader, unsigned char* buffer, size_t size, size_t* size_read) { + size_t diff = reader->end - reader->begin; + if (!diff) { + *size_read = 0; + } else if (diff < size) { + memcpy(buffer, &*reader->begin, diff); + *size_read = diff; + } else { + memcpy(buffer, &*reader->begin, size); + *size_read = size; + } + return 1; } -int YAMLStdStringWriter(std::string* str, unsigned char *buffer, size_t size) -{ - str->append((char*)buffer, size); - return 1; +int YAMLStdStringWriter(std::string* str, unsigned char* buffer, size_t size) { + str->append((char*)buffer, size); + return 1; } -int YAMLAthenaReader(athena::io::IStreamReader* reader, - unsigned char* buffer, size_t size, size_t* size_read) -{ - *size_read = reader->readUBytesToBuf(buffer, size); - return 1; +int YAMLAthenaReader(athena::io::IStreamReader* reader, unsigned char* buffer, size_t size, size_t* size_read) { + *size_read = reader->readUBytesToBuf(buffer, size); + return 1; } -int YAMLAthenaWriter(athena::io::IStreamWriter* writer, - unsigned char *buffer, size_t size) -{ - writer->writeUBytes(buffer, size); - return 1; +int YAMLAthenaWriter(athena::io::IStreamWriter* writer, unsigned char* buffer, size_t size) { + writer->writeUBytes(buffer, size); + return 1; } -YAMLDocWriter::YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader) -{ - if (!yaml_emitter_initialize(&m_emitter)) - { - HandleYAMLEmitterError(&m_emitter); - return; - } - yaml_emitter_set_unicode(&m_emitter, true); - yaml_emitter_set_width(&m_emitter, -1); - - if (reader) - { - YAMLDocReader r; - r.parse(reader); - m_rootNode = r.releaseRootNode(); - if (!m_rootNode) - m_rootNode = std::make_unique(YAML_MAPPING_NODE); - } - else - { - m_rootNode = std::make_unique(YAML_MAPPING_NODE); - } - - m_subStack.emplace_back(m_rootNode.get()); - if (classType) - { - YAMLNode* classVal = new YAMLNode(YAML_SCALAR_NODE); - classVal->m_scalarString.assign(classType); - m_rootNode->assignMapChild("DNAType", std::unique_ptr(classVal)); - } -} - -YAMLDocWriter::~YAMLDocWriter() -{ - yaml_emitter_delete(&m_emitter); -} - -bool YAMLDocWriter::finish(athena::io::IStreamWriter* fout) -{ - yaml_event_t event = {}; - - if (fout) - yaml_emitter_set_output(&m_emitter, (yaml_write_handler_t*)YAMLAthenaWriter, fout); - if (!yaml_emitter_open(&m_emitter)) - goto err; - - event.type = YAML_DOCUMENT_START_EVENT; - event.data.document_start.implicit = true; - if (!yaml_emitter_emit(&m_emitter, &event)) - goto err; - if (!RecursiveFinish(&m_emitter, *m_rootNode)) - return false; - event.type = YAML_DOCUMENT_END_EVENT; - event.data.document_end.implicit = true; - if (!yaml_emitter_emit(&m_emitter, &event)) - goto err; - - if (!yaml_emitter_close(&m_emitter) || - !yaml_emitter_flush(&m_emitter)) - goto err; - - return true; -err: +YAMLDocWriter::YAMLDocWriter(const char* classType, athena::io::IStreamReader* reader) { + if (!yaml_emitter_initialize(&m_emitter)) { HandleYAMLEmitterError(&m_emitter); + return; + } + yaml_emitter_set_unicode(&m_emitter, true); + yaml_emitter_set_width(&m_emitter, -1); + + if (reader) { + YAMLDocReader r; + r.parse(reader); + m_rootNode = r.releaseRootNode(); + if (!m_rootNode) + m_rootNode = std::make_unique(YAML_MAPPING_NODE); + } else { + m_rootNode = std::make_unique(YAML_MAPPING_NODE); + } + + m_subStack.emplace_back(m_rootNode.get()); + if (classType) { + YAMLNode* classVal = new YAMLNode(YAML_SCALAR_NODE); + classVal->m_scalarString.assign(classType); + m_rootNode->assignMapChild("DNAType", std::unique_ptr(classVal)); + } +} + +YAMLDocWriter::~YAMLDocWriter() { yaml_emitter_delete(&m_emitter); } + +bool YAMLDocWriter::finish(athena::io::IStreamWriter* fout) { + yaml_event_t event = {}; + + if (fout) + yaml_emitter_set_output(&m_emitter, (yaml_write_handler_t*)YAMLAthenaWriter, fout); + if (!yaml_emitter_open(&m_emitter)) + goto err; + + event.type = YAML_DOCUMENT_START_EVENT; + event.data.document_start.implicit = true; + if (!yaml_emitter_emit(&m_emitter, &event)) + goto err; + if (!RecursiveFinish(&m_emitter, *m_rootNode)) return false; + event.type = YAML_DOCUMENT_END_EVENT; + event.data.document_end.implicit = true; + if (!yaml_emitter_emit(&m_emitter, &event)) + goto err; + + if (!yaml_emitter_close(&m_emitter) || !yaml_emitter_flush(&m_emitter)) + goto err; + + return true; +err: + HandleYAMLEmitterError(&m_emitter); + return false; } -YAMLDocWriter::RecordRAII YAMLDocWriter::enterSubRecord(const char* name) -{ +YAMLDocWriter::RecordRAII YAMLDocWriter::enterSubRecord(const char* name) { + YAMLNode* curSub = m_subStack.back(); + if (curSub->m_type != YAML_MAPPING_NODE && curSub->m_type != YAML_SEQUENCE_NODE) + return {}; + YAMLNode* newNode = new YAMLNode(YAML_MAPPING_NODE); + if (curSub->m_type == YAML_MAPPING_NODE) + curSub->assignMapChild(name ? name : std::string_view{}, std::unique_ptr(newNode)); + else if (curSub->m_type == YAML_SEQUENCE_NODE) + curSub->m_seqChildren.emplace_back(newNode); + m_subStack.push_back(newNode); + return RecordRAII{this}; +} + +void YAMLDocWriter::_leaveSubRecord() { + if (m_subStack.size() > 1) { YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type != YAML_MAPPING_NODE && - curSub->m_type != YAML_SEQUENCE_NODE) - return {}; - YAMLNode* newNode = new YAMLNode(YAML_MAPPING_NODE); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(name?name:std::string_view{}, std::unique_ptr(newNode)); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.emplace_back(newNode); - m_subStack.push_back(newNode); - return RecordRAII{this}; -} - -void YAMLDocWriter::_leaveSubRecord() -{ - if (m_subStack.size() > 1) - { - YAMLNode* curSub = m_subStack.back(); - /* Automatically lower to scalar or sequence if there's only one unnamed node */ - if (curSub->m_mapChildren.size() == 1 && - curSub->m_mapChildren[0].first.empty()) - { - auto& item = curSub->m_mapChildren[0]; - if (item.first.empty()) - { - if (item.second->m_type == YAML_SCALAR_NODE) - { - curSub->m_type = YAML_SCALAR_NODE; - curSub->m_scalarString = std::move(item.second->m_scalarString); - curSub->m_mapChildren.clear(); - } - else if (item.second->m_type == YAML_SEQUENCE_NODE) - { - curSub->m_type = YAML_SEQUENCE_NODE; - curSub->m_seqChildren = std::move(item.second->m_seqChildren); - curSub->m_mapChildren.clear(); - } - } + /* Automatically lower to scalar or sequence if there's only one unnamed node */ + if (curSub->m_mapChildren.size() == 1 && curSub->m_mapChildren[0].first.empty()) { + auto& item = curSub->m_mapChildren[0]; + if (item.first.empty()) { + if (item.second->m_type == YAML_SCALAR_NODE) { + curSub->m_type = YAML_SCALAR_NODE; + curSub->m_scalarString = std::move(item.second->m_scalarString); + curSub->m_mapChildren.clear(); + } else if (item.second->m_type == YAML_SEQUENCE_NODE) { + curSub->m_type = YAML_SEQUENCE_NODE; + curSub->m_seqChildren = std::move(item.second->m_seqChildren); + curSub->m_mapChildren.clear(); } - m_subStack.pop_back(); + } } + m_subStack.pop_back(); + } } -YAMLDocWriter::VectorRAII YAMLDocWriter::enterSubVector(const char* name) -{ - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type != YAML_MAPPING_NODE && - curSub->m_type != YAML_SEQUENCE_NODE) - return {}; - YAMLNode* newNode = new YAMLNode(YAML_SEQUENCE_NODE); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(name?name:std::string_view{}, std::unique_ptr(newNode)); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.emplace_back(newNode); - m_subStack.push_back(newNode); - return VectorRAII{this}; +YAMLDocWriter::VectorRAII YAMLDocWriter::enterSubVector(const char* name) { + YAMLNode* curSub = m_subStack.back(); + if (curSub->m_type != YAML_MAPPING_NODE && curSub->m_type != YAML_SEQUENCE_NODE) + return {}; + YAMLNode* newNode = new YAMLNode(YAML_SEQUENCE_NODE); + if (curSub->m_type == YAML_MAPPING_NODE) + curSub->assignMapChild(name ? name : std::string_view{}, std::unique_ptr(newNode)); + else if (curSub->m_type == YAML_SEQUENCE_NODE) + curSub->m_seqChildren.emplace_back(newNode); + m_subStack.push_back(newNode); + return VectorRAII{this}; } -void YAMLDocWriter::_leaveSubVector() -{ - if (m_subStack.size() > 1) - m_subStack.pop_back(); +void YAMLDocWriter::_leaveSubVector() { + if (m_subStack.size() > 1) + m_subStack.pop_back(); } template -void YAMLDocWriter::writeVal(const char* name, const INTYPE& val) -{ - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(name?name:std::string_view{}, std::move(ValToNode(val))); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.emplace_back(std::move(ValToNode(val))); +void YAMLDocWriter::writeVal(const char* name, const INTYPE& val) { + YAMLNode* curSub = m_subStack.back(); + if (curSub->m_type == YAML_MAPPING_NODE) + curSub->assignMapChild(name ? name : std::string_view{}, std::move(ValToNode(val))); + else if (curSub->m_type == YAML_SEQUENCE_NODE) + curSub->m_seqChildren.emplace_back(std::move(ValToNode(val))); } template void YAMLDocWriter::writeVal(const char* name, const atInt8& val); @@ -674,455 +569,317 @@ template void YAMLDocWriter::writeVal(const char* name, const atVec4f& template void YAMLDocWriter::writeVal(const char* name, const bool& val); template -void YAMLDocWriter::writeVal(const char* name, const INTYPE& val, size_t byteCount) -{ - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(name?name:std::string_view{}, std::move(ValToNode(val, byteCount))); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.emplace_back(std::move(ValToNode(val, byteCount))); +void YAMLDocWriter::writeVal(const char* name, const INTYPE& val, size_t byteCount) { + YAMLNode* curSub = m_subStack.back(); + if (curSub->m_type == YAML_MAPPING_NODE) + curSub->assignMapChild(name ? name : std::string_view{}, std::move(ValToNode(val, byteCount))); + else if (curSub->m_type == YAML_SEQUENCE_NODE) + curSub->m_seqChildren.emplace_back(std::move(ValToNode(val, byteCount))); } -void YAMLDocWriter::writeBool(const char* name, const bool& val) -{ - writeVal(name, val); +void YAMLDocWriter::writeBool(const char* name, const bool& val) { writeVal(name, val); } + +void YAMLDocWriter::writeByte(const char* name, const atInt8& val) { writeVal(name, val); } + +void YAMLDocWriter::writeUByte(const char* name, const atUint8& val) { writeVal(name, val); } + +void YAMLDocWriter::writeInt16(const char* name, const atInt16& val) { writeVal(name, val); } + +void YAMLDocWriter::writeUint16(const char* name, const atUint16& val) { writeVal(name, val); } + +void YAMLDocWriter::writeInt32(const char* name, const atInt32& val) { writeVal(name, val); } + +void YAMLDocWriter::writeUint32(const char* name, const atUint32& val) { writeVal(name, val); } + +void YAMLDocWriter::writeInt64(const char* name, const atInt64& val) { writeVal(name, val); } + +void YAMLDocWriter::writeUint64(const char* name, const atUint64& val) { writeVal(name, val); } + +void YAMLDocWriter::writeFloat(const char* name, const float& val) { writeVal(name, val); } + +void YAMLDocWriter::writeDouble(const char* name, const double& val) { writeVal(name, val); } + +void YAMLDocWriter::writeVec2f(const char* name, const atVec2f& val) { writeVal(name, val); } + +void YAMLDocWriter::writeVec3f(const char* name, const atVec3f& val) { writeVal(name, val); } + +void YAMLDocWriter::writeVec4f(const char* name, const atVec4f& val) { writeVal(name, val); } + +void YAMLDocWriter::writeVec2d(const char* name, const atVec2d& val) { writeVal(name, val); } + +void YAMLDocWriter::writeVec3d(const char* name, const atVec3d& val) { writeVal(name, val); } + +void YAMLDocWriter::writeVec4d(const char* name, const atVec4d& val) { writeVal(name, val); } + +void YAMLDocWriter::writeUBytes(const char* name, const std::unique_ptr& val, size_t byteCount) { + writeVal&>(name, val, byteCount); } -void YAMLDocWriter::writeByte(const char* name, const atInt8& val) -{ - writeVal(name, val); +void YAMLDocWriter::writeString(const char* name, std::string_view val) { writeVal(name, val); } + +void YAMLDocWriter::writeWString(const char* name, std::wstring_view val) { writeVal(name, val); } + +void YAMLDocWriter::writeU16String(const char* name, std::u16string_view val) { + writeVal(name, val); } -void YAMLDocWriter::writeUByte(const char* name, const atUint8& val) -{ - writeVal(name, val); +void YAMLDocWriter::writeU32String(const char* name, std::u32string_view val) { + writeVal(name, val); } -void YAMLDocWriter::writeInt16(const char* name, const atInt16& val) -{ - writeVal(name, val); -} +void YAMLDocWriter::setStyle(YAMLNodeStyle s) { m_subStack.back()->m_style = s; } -void YAMLDocWriter::writeUint16(const char* name, const atUint16& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeInt32(const char* name, const atInt32& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeUint32(const char* name, const atUint32& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeInt64(const char* name, const atInt64& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeUint64(const char* name, const atUint64& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeFloat(const char* name, const float& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeDouble(const char* name, const double& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeVec2f(const char* name, const atVec2f& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeVec3f(const char* name, const atVec3f& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeVec4f(const char* name, const atVec4f& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeVec2d(const char* name, const atVec2d& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeVec3d(const char* name, const atVec3d& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeVec4d(const char* name, const atVec4d& val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeUBytes(const char* name, - const std::unique_ptr& val, - size_t byteCount) -{ - writeVal&>(name, val, byteCount); -} - -void YAMLDocWriter::writeString(const char* name, std::string_view val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeWString(const char* name, std::wstring_view val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeU16String(const char* name, std::u16string_view val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::writeU32String(const char* name, std::u32string_view val) -{ - writeVal(name, val); -} - -void YAMLDocWriter::setStyle(YAMLNodeStyle s) -{ - m_subStack.back()->m_style = s; -} - -static inline void InsertNode(std::vector& nodeStack, - std::unique_ptr& mapKey, - std::unique_ptr& retVal, - std::unique_ptr&& newNode) -{ - if (nodeStack.empty()) - { - retVal = std::move(newNode); - return; - } - YAMLNode* parent = nodeStack.back(); - if (parent->m_type == YAML_SEQUENCE_NODE) - { - parent->m_seqChildren.emplace_back(std::move(newNode)); - } - else if (parent->m_type == YAML_MAPPING_NODE) - { - if (!mapKey) - mapKey = std::move(newNode); - else - { - parent->assignMapChild(mapKey->m_scalarString, std::move(newNode)); - mapKey.reset(nullptr); - } +static inline void InsertNode(std::vector& nodeStack, std::unique_ptr& mapKey, + std::unique_ptr& retVal, std::unique_ptr&& newNode) { + if (nodeStack.empty()) { + retVal = std::move(newNode); + return; + } + YAMLNode* parent = nodeStack.back(); + if (parent->m_type == YAML_SEQUENCE_NODE) { + parent->m_seqChildren.emplace_back(std::move(newNode)); + } else if (parent->m_type == YAML_MAPPING_NODE) { + if (!mapKey) + mapKey = std::move(newNode); + else { + parent->assignMapChild(mapKey->m_scalarString, std::move(newNode)); + mapKey.reset(nullptr); } + } } -std::unique_ptr YAMLDocReader::ParseEvents(athena::io::IStreamReader* reader) -{ - yaml_event_t event; - if (reader) - yaml_parser_set_input(&m_parser, (yaml_read_handler_t*)YAMLAthenaReader, reader); - if (!yaml_parser_parse(&m_parser, &event)) - { - HandleYAMLParserError(&m_parser); - return std::unique_ptr(); - } - - std::vector nodeStack; - std::unique_ptr mapKey; - std::unique_ptr retVal; - int result; - for (result = yaml_parser_parse(&m_parser, &event); - event.type != YAML_STREAM_END_EVENT; - result = yaml_parser_parse(&m_parser, &event)) - { - if (!result) - { - HandleYAMLParserError(&m_parser); - return std::unique_ptr(); - } - switch (event.type) - { - case YAML_SCALAR_EVENT: - { - if (nodeStack.empty()) - { - atWarning("YAML parser stack empty; skipping scalar node"); - break; - } - std::unique_ptr newScalar(new YAMLNode(YAML_SCALAR_NODE)); - newScalar->m_scalarString.assign((char*)event.data.scalar.value, event.data.scalar.length); - if (nodeStack.empty()) - retVal = std::move(newScalar); - else - InsertNode(nodeStack, mapKey, retVal, std::move(newScalar)); - break; - } - case YAML_SEQUENCE_START_EVENT: - { - YAMLNode* newSeq = new YAMLNode(YAML_SEQUENCE_NODE); - InsertNode(nodeStack, mapKey, retVal, std::unique_ptr(newSeq)); - nodeStack.emplace_back(newSeq); - break; - } - case YAML_SEQUENCE_END_EVENT: - { - nodeStack.pop_back(); - break; - } - case YAML_MAPPING_START_EVENT: - { - YAMLNode* newMap = new YAMLNode(YAML_MAPPING_NODE); - InsertNode(nodeStack, mapKey, retVal, std::unique_ptr(newMap)); - nodeStack.emplace_back(newMap); - break; - } - case YAML_MAPPING_END_EVENT: - { - nodeStack.pop_back(); - break; - } - case YAML_DOCUMENT_END_EVENT: - { - yaml_event_delete(&event); - return retVal; - } - default: - break; - } - yaml_event_delete(&event); - } +std::unique_ptr YAMLDocReader::ParseEvents(athena::io::IStreamReader* reader) { + yaml_event_t event; + if (reader) + yaml_parser_set_input(&m_parser, (yaml_read_handler_t*)YAMLAthenaReader, reader); + if (!yaml_parser_parse(&m_parser, &event)) { + HandleYAMLParserError(&m_parser); return std::unique_ptr(); -} + } -YAMLDocReader::YAMLDocReader() -{ - if (!yaml_parser_initialize(&m_parser)) - { - HandleYAMLParserError(&m_parser); - return; + std::vector nodeStack; + std::unique_ptr mapKey; + std::unique_ptr retVal; + int result; + for (result = yaml_parser_parse(&m_parser, &event); event.type != YAML_STREAM_END_EVENT; + result = yaml_parser_parse(&m_parser, &event)) { + if (!result) { + HandleYAMLParserError(&m_parser); + return std::unique_ptr(); } -} -YAMLDocReader::~YAMLDocReader() -{ - yaml_parser_delete(&m_parser); -} - -void YAMLDocReader::reset() -{ - yaml_parser_delete(&m_parser); - if (!yaml_parser_initialize(&m_parser)) - HandleYAMLParserError(&m_parser); -} - -bool YAMLDocReader::parse(athena::io::IStreamReader* reader) -{ - std::unique_ptr newRoot = ParseEvents(reader); - if (!newRoot) - return false; - m_rootNode = std::move(newRoot); - m_subStack.clear(); - m_subStack.push_back(m_rootNode.get()); - m_seqTrackerStack.clear(); - return true; -} - -bool YAMLDocReader::ClassTypeOperation(std::function func) -{ - yaml_event_t event; - if (!yaml_parser_parse(&m_parser, &event)) - { - HandleYAMLParserError(&m_parser); - return false; + switch (event.type) { + case YAML_SCALAR_EVENT: { + if (nodeStack.empty()) { + atWarning("YAML parser stack empty; skipping scalar node"); + break; + } + std::unique_ptr newScalar(new YAMLNode(YAML_SCALAR_NODE)); + newScalar->m_scalarString.assign((char*)event.data.scalar.value, event.data.scalar.length); + if (nodeStack.empty()) + retVal = std::move(newScalar); + else + InsertNode(nodeStack, mapKey, retVal, std::move(newScalar)); + break; } - - int result; - int mappingLevel = 0; - bool inDNA = false; - for (result = yaml_parser_parse(&m_parser, &event); - event.type != YAML_STREAM_END_EVENT; - result = yaml_parser_parse(&m_parser, &event)) - { - if (!result) - { - HandleYAMLParserError(&m_parser); - return false; - } - switch (event.type) - { - case YAML_SCALAR_EVENT: - { - if (mappingLevel == 1) - { - if (inDNA) - { - bool result = func(reinterpret_cast(event.data.scalar.value)); - yaml_event_delete(&event); - return result; - } - if (!strcmp("DNAType", reinterpret_cast(event.data.scalar.value))) - inDNA = true; - } - break; - } - case YAML_MAPPING_START_EVENT: - { - ++mappingLevel; - inDNA = false; - break; - } - case YAML_MAPPING_END_EVENT: - { - --mappingLevel; - inDNA = false; - break; - } - case YAML_DOCUMENT_END_EVENT: - { - yaml_event_delete(&event); - return false; - } - default: - break; - } - yaml_event_delete(&event); + case YAML_SEQUENCE_START_EVENT: { + YAMLNode* newSeq = new YAMLNode(YAML_SEQUENCE_NODE); + InsertNode(nodeStack, mapKey, retVal, std::unique_ptr(newSeq)); + nodeStack.emplace_back(newSeq); + break; } + case YAML_SEQUENCE_END_EVENT: { + nodeStack.pop_back(); + break; + } + case YAML_MAPPING_START_EVENT: { + YAMLNode* newMap = new YAMLNode(YAML_MAPPING_NODE); + InsertNode(nodeStack, mapKey, retVal, std::unique_ptr(newMap)); + nodeStack.emplace_back(newMap); + break; + } + case YAML_MAPPING_END_EVENT: { + nodeStack.pop_back(); + break; + } + case YAML_DOCUMENT_END_EVENT: { + yaml_event_delete(&event); + return retVal; + } + default: + break; + } + yaml_event_delete(&event); + } + return std::unique_ptr(); +} + +YAMLDocReader::YAMLDocReader() { + if (!yaml_parser_initialize(&m_parser)) { + HandleYAMLParserError(&m_parser); + return; + } +} +YAMLDocReader::~YAMLDocReader() { yaml_parser_delete(&m_parser); } + +void YAMLDocReader::reset() { + yaml_parser_delete(&m_parser); + if (!yaml_parser_initialize(&m_parser)) + HandleYAMLParserError(&m_parser); +} + +bool YAMLDocReader::parse(athena::io::IStreamReader* reader) { + std::unique_ptr newRoot = ParseEvents(reader); + if (!newRoot) return false; + m_rootNode = std::move(newRoot); + m_subStack.clear(); + m_subStack.push_back(m_rootNode.get()); + m_seqTrackerStack.clear(); + return true; } -bool YAMLDocReader::ValidateClassType(const char* expectedType) -{ - if (!expectedType) - return false; +bool YAMLDocReader::ClassTypeOperation(std::function func) { + yaml_event_t event; + if (!yaml_parser_parse(&m_parser, &event)) { + HandleYAMLParserError(&m_parser); + return false; + } - return ClassTypeOperation([&](const char* dnaType) -> bool - { - return (strcmp(expectedType, dnaType) == 0); - }); -} - -YAMLDocReader::RecordRAII YAMLDocReader::enterSubRecord(const char* name) -{ - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type == YAML_SEQUENCE_NODE) - { - int& seqIdx = m_seqTrackerStack.back(); - m_subStack.push_back(curSub->m_seqChildren[seqIdx++].get()); - if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) - m_seqTrackerStack.push_back(0); - return RecordRAII{this}; + int result; + int mappingLevel = 0; + bool inDNA = false; + for (result = yaml_parser_parse(&m_parser, &event); event.type != YAML_STREAM_END_EVENT; + result = yaml_parser_parse(&m_parser, &event)) { + if (!result) { + HandleYAMLParserError(&m_parser); + return false; } - else if (!name) - { - atError("Expected YAML sequence"); - } - for (const auto& item : curSub->m_mapChildren) - { - if (!item.first.compare(name)) - { - m_subStack.push_back(item.second.get()); - if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) - m_seqTrackerStack.push_back(0); - return RecordRAII{this}; + switch (event.type) { + case YAML_SCALAR_EVENT: { + if (mappingLevel == 1) { + if (inDNA) { + bool result = func(reinterpret_cast(event.data.scalar.value)); + yaml_event_delete(&event); + return result; } + if (!strcmp("DNAType", reinterpret_cast(event.data.scalar.value))) + inDNA = true; + } + break; } - return {}; + case YAML_MAPPING_START_EVENT: { + ++mappingLevel; + inDNA = false; + break; + } + case YAML_MAPPING_END_EVENT: { + --mappingLevel; + inDNA = false; + break; + } + case YAML_DOCUMENT_END_EVENT: { + yaml_event_delete(&event); + return false; + } + default: + break; + } + yaml_event_delete(&event); + } + return false; } -void YAMLDocReader::_leaveSubRecord() -{ - if (m_subStack.size() > 1) - { - if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) - m_seqTrackerStack.pop_back(); - m_subStack.pop_back(); - } +bool YAMLDocReader::ValidateClassType(const char* expectedType) { + if (!expectedType) + return false; + + return ClassTypeOperation([&](const char* dnaType) -> bool { return (strcmp(expectedType, dnaType) == 0); }); } -YAMLDocReader::VectorRAII YAMLDocReader::enterSubVector(const char* name, size_t& countOut) -{ - YAMLNode* curSub = m_subStack.back(); - if (!name && curSub->m_type == YAML_SEQUENCE_NODE) - { - m_subStack.push_back(curSub); +YAMLDocReader::RecordRAII YAMLDocReader::enterSubRecord(const char* name) { + YAMLNode* curSub = m_subStack.back(); + if (curSub->m_type == YAML_SEQUENCE_NODE) { + int& seqIdx = m_seqTrackerStack.back(); + m_subStack.push_back(curSub->m_seqChildren[seqIdx++].get()); + if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) + m_seqTrackerStack.push_back(0); + return RecordRAII{this}; + } else if (!name) { + atError("Expected YAML sequence"); + } + for (const auto& item : curSub->m_mapChildren) { + if (!item.first.compare(name)) { + m_subStack.push_back(item.second.get()); + if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) m_seqTrackerStack.push_back(0); - countOut = curSub->m_seqChildren.size(); - return VectorRAII{this}; + return RecordRAII{this}; } - else - { - for (const auto& item : curSub->m_mapChildren) - { - if (!item.first.compare(name)) - { - YAMLNode* nextSub = item.second.get(); - if (nextSub->m_type == YAML_SEQUENCE_NODE) - { - countOut = nextSub->m_seqChildren.size(); - } - else - { - atError("'%s' is not a vector field", name); - countOut = 0; - } - m_subStack.push_back(nextSub); - m_seqTrackerStack.push_back(0); - return VectorRAII{this}; - } - } - } - countOut = 0; - return {}; + } + return {}; } -void YAMLDocReader::_leaveSubVector() -{ - if (m_subStack.size() > 1) - { - m_subStack.pop_back(); - m_seqTrackerStack.pop_back(); +void YAMLDocReader::_leaveSubRecord() { + if (m_subStack.size() > 1) { + if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) + m_seqTrackerStack.pop_back(); + m_subStack.pop_back(); + } +} + +YAMLDocReader::VectorRAII YAMLDocReader::enterSubVector(const char* name, size_t& countOut) { + YAMLNode* curSub = m_subStack.back(); + if (!name && curSub->m_type == YAML_SEQUENCE_NODE) { + m_subStack.push_back(curSub); + m_seqTrackerStack.push_back(0); + countOut = curSub->m_seqChildren.size(); + return VectorRAII{this}; + } else { + for (const auto& item : curSub->m_mapChildren) { + if (!item.first.compare(name)) { + YAMLNode* nextSub = item.second.get(); + if (nextSub->m_type == YAML_SEQUENCE_NODE) { + countOut = nextSub->m_seqChildren.size(); + } else { + atError("'%s' is not a vector field", name); + countOut = 0; + } + m_subStack.push_back(nextSub); + m_seqTrackerStack.push_back(0); + return VectorRAII{this}; + } } + } + countOut = 0; + return {}; +} + +void YAMLDocReader::_leaveSubVector() { + if (m_subStack.size() > 1) { + m_subStack.pop_back(); + m_seqTrackerStack.pop_back(); + } } template -RETURNTYPE YAMLDocReader::readVal(const char* name) -{ - if (m_subStack.size()) - { - const YAMLNode* mnode = m_subStack.back(); - if (mnode->m_type == YAML_SCALAR_NODE) - { - return NodeToVal(mnode); - } - else if (mnode->m_type == YAML_SEQUENCE_NODE) - { - int& seqIdx = m_seqTrackerStack.back(); - return NodeToVal(mnode->m_seqChildren[seqIdx++].get()); - } - else if (mnode->m_type == YAML_MAPPING_NODE && name) - { - for (const auto& item : mnode->m_mapChildren) - { - if (!item.first.compare(name)) - { - return NodeToVal(item.second.get()); - } - } +RETURNTYPE YAMLDocReader::readVal(const char* name) { + if (m_subStack.size()) { + const YAMLNode* mnode = m_subStack.back(); + if (mnode->m_type == YAML_SCALAR_NODE) { + return NodeToVal(mnode); + } else if (mnode->m_type == YAML_SEQUENCE_NODE) { + int& seqIdx = m_seqTrackerStack.back(); + return NodeToVal(mnode->m_seqChildren[seqIdx++].get()); + } else if (mnode->m_type == YAML_MAPPING_NODE && name) { + for (const auto& item : mnode->m_mapChildren) { + if (!item.first.compare(name)) { + return NodeToVal(item.second.get()); } + } } - if (name) - atWarning("Unable to find field '%s'; returning 0", name); - return RETURNTYPE(); + } + if (name) + atWarning("Unable to find field '%s'; returning 0", name); + return RETURNTYPE(); } template atInt8 YAMLDocReader::readVal(const char* name); @@ -1137,308 +894,226 @@ template atVec3f YAMLDocReader::readVal(const char* name); template atVec4f YAMLDocReader::readVal(const char* name); template bool YAMLDocReader::readVal(const char* name); -bool YAMLDocReader::readBool(const char* name) -{ - return readVal(name); +bool YAMLDocReader::readBool(const char* name) { return readVal(name); } + +atInt8 YAMLDocReader::readByte(const char* name) { return readVal(name); } + +atUint8 YAMLDocReader::readUByte(const char* name) { return readVal(name); } + +atInt16 YAMLDocReader::readInt16(const char* name) { return readVal(name); } + +atUint16 YAMLDocReader::readUint16(const char* name) { return readVal(name); } + +atInt32 YAMLDocReader::readInt32(const char* name) { return readVal(name); } + +atUint32 YAMLDocReader::readUint32(const char* name) { return readVal(name); } + +atInt64 YAMLDocReader::readInt64(const char* name) { return readVal(name); } + +atUint64 YAMLDocReader::readUint64(const char* name) { return readVal(name); } + +float YAMLDocReader::readFloat(const char* name) { return readVal(name); } + +double YAMLDocReader::readDouble(const char* name) { return readVal(name); } + +atVec2f YAMLDocReader::readVec2f(const char* name) { return readVal(name); } + +atVec3f YAMLDocReader::readVec3f(const char* name) { return readVal(name); } +atVec4f YAMLDocReader::readVec4f(const char* name) { return readVal(name); } + +atVec2d YAMLDocReader::readVec2d(const char* name) { return readVal(name); } + +atVec3d YAMLDocReader::readVec3d(const char* name) { return readVal(name); } + +atVec4d YAMLDocReader::readVec4d(const char* name) { return readVal(name); } + +std::unique_ptr YAMLDocReader::readUBytes(const char* name) { + return readVal>(name); } -atInt8 YAMLDocReader::readByte(const char* name) -{ - return readVal(name); -} +std::string YAMLDocReader::readString(const char* name) { return readVal(name); } -atUint8 YAMLDocReader::readUByte(const char* name) -{ - return readVal(name); -} +std::wstring YAMLDocReader::readWString(const char* name) { return readVal(name); } -atInt16 YAMLDocReader::readInt16(const char* name) -{ - return readVal(name); -} - -atUint16 YAMLDocReader::readUint16(const char* name) -{ - return readVal(name); -} - -atInt32 YAMLDocReader::readInt32(const char* name) -{ - return readVal(name); -} - -atUint32 YAMLDocReader::readUint32(const char* name) -{ - return readVal(name); -} - -atInt64 YAMLDocReader::readInt64(const char* name) -{ - return readVal(name); -} - -atUint64 YAMLDocReader::readUint64(const char* name) -{ - return readVal(name); -} - -float YAMLDocReader::readFloat(const char* name) -{ - return readVal(name); -} - -double YAMLDocReader::readDouble(const char* name) -{ - return readVal(name); -} - -atVec2f YAMLDocReader::readVec2f(const char* name) -{ - return readVal(name); -} - -atVec3f YAMLDocReader::readVec3f(const char* name) -{ - return readVal(name); -} -atVec4f YAMLDocReader::readVec4f(const char* name) -{ - return readVal(name); -} - -atVec2d YAMLDocReader::readVec2d(const char* name) -{ - return readVal(name); -} - -atVec3d YAMLDocReader::readVec3d(const char* name) -{ - return readVal(name); -} - -atVec4d YAMLDocReader::readVec4d(const char* name) -{ - return readVal(name); -} - -std::unique_ptr YAMLDocReader::readUBytes(const char* name) -{ - return readVal>(name); -} - -std::string YAMLDocReader::readString(const char* name) -{ - return readVal(name); -} - -std::wstring YAMLDocReader::readWString(const char* name) -{ - return readVal(name); -} - -static inline bool EmitKeyScalar(yaml_emitter_t* doc, const char* val) -{ - yaml_event_t event; - if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)val, - strlen(val), true, true, YAML_PLAIN_SCALAR_STYLE)) - return false; - return yaml_emitter_emit(doc, &event) != 0; -} - -static inline yaml_scalar_style_t ScalarStyle(const YAMLNode& node) -{ - for (const auto& ch : node.m_scalarString) - if (ch == '\n') - return YAML_LITERAL_SCALAR_STYLE; - return YAML_ANY_SCALAR_STYLE; -} - -static inline yaml_sequence_style_t SequenceStyle(const YAMLNode& node) -{ - if (node.m_style == YAMLNodeStyle::Flow) - return YAML_FLOW_SEQUENCE_STYLE; - else if (node.m_style == YAMLNodeStyle::Block) - return YAML_BLOCK_SEQUENCE_STYLE; - - size_t count = 0; - for (const auto& item : node.m_seqChildren) - { - if (item->m_type != YAML_SCALAR_NODE) - return YAML_BLOCK_SEQUENCE_STYLE; - size_t strLen = item->m_scalarString.size(); - size_t thisCount = strLen / 10; - if (!thisCount) - thisCount = 1; - count += thisCount; - } - return (count > 6) ? YAML_BLOCK_SEQUENCE_STYLE : YAML_FLOW_SEQUENCE_STYLE; -} - -static inline yaml_mapping_style_t MappingStyle(const YAMLNode& node) -{ - if (node.m_style == YAMLNodeStyle::Flow) - return YAML_FLOW_MAPPING_STYLE; - else if (node.m_style == YAMLNodeStyle::Block) - return YAML_BLOCK_MAPPING_STYLE; - - size_t count = 0; - for (const auto& item : node.m_mapChildren) - { - if (item.second->m_type != YAML_SCALAR_NODE) - return YAML_BLOCK_MAPPING_STYLE; - size_t strLen = item.second->m_scalarString.size(); - size_t thisCount = strLen / 10; - if (!thisCount) - thisCount = 1; - count += thisCount; - } - return (count > 6) ? YAML_BLOCK_MAPPING_STYLE : YAML_FLOW_MAPPING_STYLE; -} - -bool YAMLDocWriter::RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node) -{ - yaml_event_t event; - if (node.m_type == YAML_SCALAR_NODE) - { - if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)node.m_scalarString.c_str(), - node.m_scalarString.length(), true, true, ScalarStyle(node)) || - !yaml_emitter_emit(doc, &event)) - goto err; - } - else if (node.m_type == YAML_SEQUENCE_NODE) - { - if (!yaml_sequence_start_event_initialize(&event, nullptr, nullptr, 1, SequenceStyle(node)) || - !yaml_emitter_emit(doc, &event)) - goto err; - for (const auto& item : node.m_seqChildren) - { - if (!RecursiveFinish(doc, *item)) - goto err; - } - if (!yaml_sequence_end_event_initialize(&event) || - !yaml_emitter_emit(doc, &event)) - goto err; - } - else if (node.m_type == YAML_MAPPING_NODE) - { - if (!yaml_mapping_start_event_initialize(&event, nullptr, nullptr, true, MappingStyle(node)) || - !yaml_emitter_emit(doc, &event)) - goto err; - for (const auto& item : node.m_mapChildren) - { - if (!EmitKeyScalar(doc, item.first.c_str())) - goto err; - if (!RecursiveFinish(doc, *item.second)) - goto err; - } - event.type = YAML_MAPPING_END_EVENT; - if (!yaml_mapping_end_event_initialize(&event) || - !yaml_emitter_emit(doc, &event)) - goto err; - - } - return true; -err: - HandleYAMLEmitterError(doc); +static inline bool EmitKeyScalar(yaml_emitter_t* doc, const char* val) { + yaml_event_t event; + if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)val, strlen(val), true, true, + YAML_PLAIN_SCALAR_STYLE)) return false; + return yaml_emitter_emit(doc, &event) != 0; +} + +static inline yaml_scalar_style_t ScalarStyle(const YAMLNode& node) { + for (const auto& ch : node.m_scalarString) + if (ch == '\n') + return YAML_LITERAL_SCALAR_STYLE; + return YAML_ANY_SCALAR_STYLE; +} + +static inline yaml_sequence_style_t SequenceStyle(const YAMLNode& node) { + if (node.m_style == YAMLNodeStyle::Flow) + return YAML_FLOW_SEQUENCE_STYLE; + else if (node.m_style == YAMLNodeStyle::Block) + return YAML_BLOCK_SEQUENCE_STYLE; + + size_t count = 0; + for (const auto& item : node.m_seqChildren) { + if (item->m_type != YAML_SCALAR_NODE) + return YAML_BLOCK_SEQUENCE_STYLE; + size_t strLen = item->m_scalarString.size(); + size_t thisCount = strLen / 10; + if (!thisCount) + thisCount = 1; + count += thisCount; + } + return (count > 6) ? YAML_BLOCK_SEQUENCE_STYLE : YAML_FLOW_SEQUENCE_STYLE; +} + +static inline yaml_mapping_style_t MappingStyle(const YAMLNode& node) { + if (node.m_style == YAMLNodeStyle::Flow) + return YAML_FLOW_MAPPING_STYLE; + else if (node.m_style == YAMLNodeStyle::Block) + return YAML_BLOCK_MAPPING_STYLE; + + size_t count = 0; + for (const auto& item : node.m_mapChildren) { + if (item.second->m_type != YAML_SCALAR_NODE) + return YAML_BLOCK_MAPPING_STYLE; + size_t strLen = item.second->m_scalarString.size(); + size_t thisCount = strLen / 10; + if (!thisCount) + thisCount = 1; + count += thisCount; + } + return (count > 6) ? YAML_BLOCK_MAPPING_STYLE : YAML_FLOW_MAPPING_STYLE; +} + +bool YAMLDocWriter::RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node) { + yaml_event_t event; + if (node.m_type == YAML_SCALAR_NODE) { + if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)node.m_scalarString.c_str(), + node.m_scalarString.length(), true, true, ScalarStyle(node)) || + !yaml_emitter_emit(doc, &event)) + goto err; + } else if (node.m_type == YAML_SEQUENCE_NODE) { + if (!yaml_sequence_start_event_initialize(&event, nullptr, nullptr, 1, SequenceStyle(node)) || + !yaml_emitter_emit(doc, &event)) + goto err; + for (const auto& item : node.m_seqChildren) { + if (!RecursiveFinish(doc, *item)) + goto err; + } + if (!yaml_sequence_end_event_initialize(&event) || !yaml_emitter_emit(doc, &event)) + goto err; + } else if (node.m_type == YAML_MAPPING_NODE) { + if (!yaml_mapping_start_event_initialize(&event, nullptr, nullptr, true, MappingStyle(node)) || + !yaml_emitter_emit(doc, &event)) + goto err; + for (const auto& item : node.m_mapChildren) { + if (!EmitKeyScalar(doc, item.first.c_str())) + goto err; + if (!RecursiveFinish(doc, *item.second)) + goto err; + } + event.type = YAML_MAPPING_END_EVENT; + if (!yaml_mapping_end_event_initialize(&event) || !yaml_emitter_emit(doc, &event)) + goto err; + } + return true; +err: + HandleYAMLEmitterError(doc); + return false; } static const std::string base64_chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; +static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } -static inline bool is_base64(unsigned char c) -{ - return (isalnum(c) || (c == '+') || (c == '/')); +std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + ret.reserve(in_len * 4 / 3); + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (i = 0; (i < 4); i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) { + for (j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while ((i++ < 3)) + ret += '='; + } + + return ret; +} +std::unique_ptr base64_decode(std::string_view encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::unique_ptr ret(new atUint8[in_len * 3 / 4]); + atUint8* retBuf = ret.get(); + + while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; + in_++; + if (i == 4) { + for (i = 0; i < 4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + *retBuf++ = char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) + char_array_4[j] = 0; + + for (j = 0; j < 4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) + *retBuf++ = char_array_3[j]; + } + + return ret; } -std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len) -{ - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - ret.reserve(in_len * 4 / 3); - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for(i = 0; (i <4) ; i++) - ret += base64_chars[char_array_4[i]]; - i = 0; - } - } - - if (i) - { - for(j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars[char_array_4[j]]; - - while((i++ < 3)) - ret += '='; - - } - - return ret; - -} -std::unique_ptr base64_decode(std::string_view encoded_string) -{ - int in_len = encoded_string.size(); - int i = 0; - int j = 0; - int in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::unique_ptr ret(new atUint8[in_len * 3 / 4]); - atUint8* retBuf = ret.get(); - - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; in_++; - if (i ==4) { - for (i = 0; i <4; i++) - char_array_4[i] = base64_chars.find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - *retBuf++ = char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j <4; j++) - char_array_4[j] = 0; - - for (j = 0; j <4; j++) - char_array_4[j] = base64_chars.find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) *retBuf++ = char_array_3[j]; - } - - return ret; -} - -} +} // namespace athena::io diff --git a/src/athena/Dir.cpp b/src/athena/Dir.cpp index 74b0389..0d432cf 100644 --- a/src/athena/Dir.cpp +++ b/src/athena/Dir.cpp @@ -18,89 +18,70 @@ #define realpath(__name, __resolved) _fullpath((__name), (__resolved), 4096) #endif -namespace athena -{ -Dir::Dir(std::string_view path) - : m_path(path) -{ -} +namespace athena { +Dir::Dir(std::string_view path) : m_path(path) {} -std::string Dir::absolutePath() const -{ - return FileInfo(m_path).absoluteFilePath(); -} - -bool Dir::isDir() const -{ - atStat64_t st; - int e = atStat64(m_path.c_str(), &st); - if (e < 0) - return false; - - return (S_ISDIR(st.st_mode)); -} - -bool Dir::cd(std::string_view path) -{ - Dir tmp(path); - if (tmp.isDir()) - { - m_path = path; - return true; - } +std::string Dir::absolutePath() const { return FileInfo(m_path).absoluteFilePath(); } +bool Dir::isDir() const { + atStat64_t st; + int e = atStat64(m_path.c_str(), &st); + if (e < 0) return false; + + return (S_ISDIR(st.st_mode)); } -bool Dir::rm(std::string_view path) -{ - return !(remove((m_path + "/" + path.data()).c_str()) < 0); +bool Dir::cd(std::string_view path) { + Dir tmp(path); + if (tmp.isDir()) { + m_path = path; + return true; + } + + return false; } -bool Dir::touch() -{ - srand(time(NULL)); - atUint64 tmp = utility::rand64(); - std::string tmpFile = utility::sprintf("%" PRIX64 ".tmp", tmp); - bool ret = FileInfo(m_path + "/" + tmpFile).touch(); - if (ret) - return rm(tmpFile); - return false; +bool Dir::rm(std::string_view path) { return !(remove((m_path + "/" + path.data()).c_str()) < 0); } + +bool Dir::touch() { + srand(time(NULL)); + atUint64 tmp = utility::rand64(); + std::string tmpFile = utility::sprintf("%" PRIX64 ".tmp", tmp); + bool ret = FileInfo(m_path + "/" + tmpFile).touch(); + if (ret) + return rm(tmpFile); + return false; } -bool Dir::mkdir(std::string_view dir, mode_t mode) -{ +bool Dir::mkdir(std::string_view dir, mode_t mode) { #if _WIN32 - return !(::_mkdir(dir.data()) < 0); + return !(::_mkdir(dir.data()) < 0); #else - return !(::mkdir(dir.data(), mode) < 0); + return !(::mkdir(dir.data(), mode) < 0); #endif } -bool Dir::mkpath(std::string_view path, mode_t mode) -{ - std::vector dirs = utility::split(path, '/'); - if (dirs.empty()) - dirs = utility::split(path, '\\'); - if (dirs.empty()) - return false; +bool Dir::mkpath(std::string_view path, mode_t mode) { + std::vector dirs = utility::split(path, '/'); + if (dirs.empty()) + dirs = utility::split(path, '\\'); + if (dirs.empty()) + return false; - bool ret = false; - std::string newPath; - for (const std::string& dir : dirs) - { - if (dir.size() == 2 && dir[1] == ':') - { - newPath += dir + "//"; - continue; - } - newPath += "/" + dir; - ret = mkdir(newPath, mode); + bool ret = false; + std::string newPath; + for (const std::string& dir : dirs) { + if (dir.size() == 2 && dir[1] == ':') { + newPath += dir + "//"; + continue; } + newPath += "/" + dir; + ret = mkdir(newPath, mode); + } - // we only care if the last directory was created - return ret; -} - + // we only care if the last directory was created + return ret; } +} // namespace athena diff --git a/src/athena/FileInfo.cpp b/src/athena/FileInfo.cpp index 96eabcb..fb47e01 100644 --- a/src/athena/FileInfo.cpp +++ b/src/athena/FileInfo.cpp @@ -29,168 +29,149 @@ #define realpath(__name, __resolved) _fullpath((__resolved), (__name), 4096) #endif -namespace athena -{ +namespace athena { -FileInfo::FileInfo(std::string_view path) - : m_path(path) -{ +FileInfo::FileInfo(std::string_view path) : m_path(path) {} + +std::string FileInfo::absolutePath() const { + std::string path = absoluteFilePath(); + size_t pos = path.find_last_of('/'); + if (pos == std::string::npos) + pos = path.find_last_of('\\'); + if (pos == std::string::npos) + return path; + + return path.substr(0, pos + 1); } -std::string FileInfo::absolutePath() const -{ - std::string path = absoluteFilePath(); - size_t pos = path.find_last_of('/'); - if (pos == std::string::npos) - pos = path.find_last_of('\\'); - if (pos == std::string::npos) - return path; - - return path.substr(0, pos+1); +std::string FileInfo::absoluteFilePath() const { + char ret[4096]; + realpath(m_path.c_str(), ret); + return ret; } -std::string FileInfo::absoluteFilePath() const -{ - char ret[4096]; - realpath(m_path.c_str(), ret); - return ret; +std::string FileInfo::filename() const { + size_t pos = m_path.find_last_of('/'); + if (pos == std::string::npos) + pos = m_path.find_last_of('\\'); + if (pos == std::string::npos) + return m_path; + return m_path.substr(pos + 1); } -std::string FileInfo::filename() const -{ - size_t pos = m_path.find_last_of('/'); - if (pos == std::string::npos) - pos = m_path.find_last_of('\\'); - if (pos == std::string::npos) - return m_path; - return m_path.substr(pos + 1); +std::string FileInfo::extension() const { + size_t pos = m_path.find_last_of('.'); + if (pos == std::string::npos) + return std::string(); + + return m_path.substr(pos + 1); } -std::string FileInfo::extension() const -{ - size_t pos = m_path.find_last_of('.'); - if (pos == std::string::npos) - return std::string(); +atUint64 FileInfo::size() const { return utility::fileSize(m_path); } - return m_path.substr(pos + 1); +bool FileInfo::exists() const { + atStat64_t st; + int e = atStat64(m_path.c_str(), &st); + + if (e < 0) + return false; + + return (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)); } -atUint64 FileInfo::size() const -{ - return utility::fileSize(m_path); +bool FileInfo::isLink() const { + atStat64_t st; + int e = atStat64(m_path.c_str(), &st); + if (e < 0) + return false; + + return (S_ISLNK(st.st_mode)); } -bool FileInfo::exists() const -{ - atStat64_t st; - int e = atStat64(m_path.c_str(), &st); +bool FileInfo::isFile() const { + atStat64_t st; + int e = atStat64(m_path.c_str(), &st); + if (e < 0) + return false; - if (e < 0) - return false; - - return (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)); + return (S_ISREG(st.st_mode)); } -bool FileInfo::isLink() const -{ - atStat64_t st; - int e = atStat64(m_path.c_str(), &st); - if (e < 0) - return false; - - return (S_ISLNK(st.st_mode)); -} - -bool FileInfo::isFile() const -{ - atStat64_t st; - int e = atStat64(m_path.c_str(), &st); - if (e < 0) - return false; - - return (S_ISREG(st.st_mode)); -} - -bool FileInfo::touch() const -{ +bool FileInfo::touch() const { #if defined(__GNUC__) && !(defined(HW_DOL) || defined(HW_RVL) || defined(GEKKO)) - atStat64_t st; - if (atStat64(m_path.c_str(), &st) < 0) { - (void)athena::io::FileWriter(m_path); - return true; - } - if (utimes(m_path.c_str(), NULL) < 0) { - return false; - } + atStat64_t st; + if (atStat64(m_path.c_str(), &st) < 0) { + (void)athena::io::FileWriter(m_path); + return true; + } + if (utimes(m_path.c_str(), NULL) < 0) { + return false; + } #elif defined(_WIN32) - FILETIME modtime; - SYSTEMTIME st; - HANDLE fh; - wchar_t date[80], time[80]; + FILETIME modtime; + SYSTEMTIME st; + HANDLE fh; + wchar_t date[80], time[80]; #if !WINDOWS_STORE - fh = CreateFileA(m_path.c_str(), GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, CREATE_NEW, 0, NULL); - - if (fh == INVALID_HANDLE_VALUE) - return false; + fh = CreateFileA(m_path.c_str(), GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, CREATE_NEW, 0, NULL); - /* - * Use GetFileTime() to get the file modification time. - */ - if (GetFileTime(fh, NULL, NULL, &modtime) == 0) - { - CloseHandle(fh); - return false; - } - - FileTimeToSystemTime(&modtime, &st); - if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 || - GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0) - { - CloseHandle(fh); - return false; - } - - /* - * Use SetFileTime() to change the file modification time - * to the current time. - */ - GetSystemTime(&st); - if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 || - GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0) - { - CloseHandle(fh); - return false; - } - SystemTimeToFileTime(&st, &modtime); - if (SetFileTime(fh, NULL, NULL, &modtime) == 0) - { - CloseHandle(fh); - return false; - } + if (fh == INVALID_HANDLE_VALUE) + return false; + /* + * Use GetFileTime() to get the file modification time. + */ + if (GetFileTime(fh, NULL, NULL, &modtime) == 0) { CloseHandle(fh); + return false; + } + + FileTimeToSystemTime(&modtime, &st); + if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 || + GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0) { + CloseHandle(fh); + return false; + } + + /* + * Use SetFileTime() to change the file modification time + * to the current time. + */ + GetSystemTime(&st); + if (GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, date, sizeof date / sizeof date[0]) == 0 || + GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, time, sizeof time / sizeof time[0]) == 0) { + CloseHandle(fh); + return false; + } + SystemTimeToFileTime(&st, &modtime); + if (SetFileTime(fh, NULL, NULL, &modtime) == 0) { + CloseHandle(fh); + return false; + } + + CloseHandle(fh); #endif #elif (defined(HW_RVL) || defined(HW_DOL)) && defined(GEKKO) - // Generic portable version, not extremely reliable but does work - atUint64 val = 0xCDCDCDCDCD; - { - athena::io::FileReader reader(m_path.c_str()); - if (reader.isOpen()) - val = reader.readUint64(); - } + // Generic portable version, not extremely reliable but does work + atUint64 val = 0xCDCDCDCDCD; + { + athena::io::FileReader reader(m_path.c_str()); + if (reader.isOpen()) + val = reader.readUint64(); + } - { - athena::io::FileWriter writer(m_path, false); - if (val != 0xCDCDCDCDCD && writer.isOpen()) - writer.writeUint64(val); - else if (!writer.isOpen()) - return false; - } + { + athena::io::FileWriter writer(m_path, false); + if (val != 0xCDCDCDCDCD && writer.isOpen()) + writer.writeUint64(val); + else if (!writer.isOpen()) + return false; + } #endif - return true; + return true; } -} +} // namespace athena diff --git a/src/athena/FileReader.cpp b/src/athena/FileReader.cpp index ecff39e..6ea301d 100644 --- a/src/athena/FileReader.cpp +++ b/src/athena/FileReader.cpp @@ -7,201 +7,170 @@ #include "osx_largefilewrapper.h" #endif -namespace athena::io -{ +namespace athena::io { FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr) - : m_fileHandle(nullptr), - m_cacheData(nullptr), - m_offset(0), - m_globalErr(globalErr) -{ - m_filename = filename; - open(); - setCacheSize(cacheSize); +: m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) { + m_filename = filename; + open(); + setCacheSize(cacheSize); } FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr) - : m_fileHandle(nullptr), - m_cacheData(nullptr), - m_offset(0), - m_globalErr(globalErr) -{ - m_filename = utility::wideToUtf8(filename); - open(); - setCacheSize(cacheSize); +: m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) { + m_filename = utility::wideToUtf8(filename); + open(); + setCacheSize(cacheSize); } -FileReader::~FileReader() -{ - if (isOpen()) - close(); +FileReader::~FileReader() { + if (isOpen()) + close(); } -void FileReader::open() -{ - m_fileHandle = fopen(m_filename.c_str(), "rb"); +void FileReader::open() { + m_fileHandle = fopen(m_filename.c_str(), "rb"); - if (!m_fileHandle) - { - std::string _filename = filename(); - if (m_globalErr) - atError("File not found '%s'", _filename.c_str()); - setError(); - return; - } - - // reset error - m_hasError = false; -} - -void FileReader::close() -{ - if (!m_fileHandle) - { - if (m_globalErr) - atError("Cannot close an unopened stream"); - setError(); - return; - } - - fclose(m_fileHandle); - m_fileHandle = NULL; + if (!m_fileHandle) { + std::string _filename = filename(); + if (m_globalErr) + atError("File not found '%s'", _filename.c_str()); + setError(); return; + } + + // reset error + m_hasError = false; } -void FileReader::seek(atInt64 pos, SeekOrigin origin) -{ - if (!isOpen()) - return; +void FileReader::close() { + if (!m_fileHandle) { + if (m_globalErr) + atError("Cannot close an unopened stream"); + setError(); + return; + } - // check block position - if (m_blockSize > 0) - { - atUint64 oldOff = m_offset; - switch(origin) - { - case SeekOrigin::Begin: - m_offset = pos; - break; - case SeekOrigin::Current: - m_offset += pos; - break; - case SeekOrigin::End: - m_offset = length() - pos; - break; - } - if (m_offset > length()) - { - oldOff = m_offset; - if (m_globalErr) - atError("Unable to seek in file"); - setError(); - return; - } - - size_t block = m_offset / m_blockSize; - if (block != m_curBlock) - { - fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET); - fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle); - m_curBlock = (atInt32)block; - } - } - else if (fseeko64(m_fileHandle, pos, (int)origin) != 0) - { - if (m_globalErr) - atError("Unable to seek in file"); - setError(); - } + fclose(m_fileHandle); + m_fileHandle = NULL; + return; } -atUint64 FileReader::position() const -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open"); - return 0; +void FileReader::seek(atInt64 pos, SeekOrigin origin) { + if (!isOpen()) + return; + + // check block position + if (m_blockSize > 0) { + atUint64 oldOff = m_offset; + switch (origin) { + case SeekOrigin::Begin: + m_offset = pos; + break; + case SeekOrigin::Current: + m_offset += pos; + break; + case SeekOrigin::End: + m_offset = length() - pos; + break; + } + if (m_offset > length()) { + oldOff = m_offset; + if (m_globalErr) + atError("Unable to seek in file"); + setError(); + return; } - if (m_blockSize > 0) - return m_offset; - else - return ftello64(m_fileHandle); -} - -atUint64 FileReader::length() const -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open"); - return 0; + size_t block = m_offset / m_blockSize; + if (block != m_curBlock) { + fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET); + fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle); + m_curBlock = (atInt32)block; } - - return utility::fileSize(m_filename); + } else if (fseeko64(m_fileHandle, pos, (int)origin) != 0) { + if (m_globalErr) + atError("Unable to seek in file"); + setError(); + } } -atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open for reading"); - setError(); - return 0; - } - - if (m_blockSize <= 0) - return fread(buf, 1, len, m_fileHandle); - else - { - atUint64 fs = utility::fileSize(m_filename); - if (m_offset >= fs) - return 0; - if (m_offset + len >= fs) - len = fs - m_offset; - - size_t block = m_offset / m_blockSize; - atUint64 cacheOffset = m_offset % m_blockSize; - atUint64 cacheSize; - atUint64 rem = len; - atUint8* dst = (atUint8*)buf; - - while (rem) - { - if (block != m_curBlock) - { - fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET); - fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle); - m_curBlock = (atInt32)block; - } - - cacheSize = rem; - if (cacheSize + cacheOffset > m_blockSize) - cacheSize = m_blockSize - cacheOffset; - - memmove(dst, m_cacheData.get() + cacheOffset, cacheSize); - dst += cacheSize; - rem -= cacheSize; - cacheOffset = 0; - ++block; - } - m_offset += len; - return dst - (atUint8*)buf; +atUint64 FileReader::position() const { + if (!isOpen()) { + if (m_globalErr) + atError("File not open"); + return 0; + } + + if (m_blockSize > 0) + return m_offset; + else + return ftello64(m_fileHandle); +} + +atUint64 FileReader::length() const { + if (!isOpen()) { + if (m_globalErr) + atError("File not open"); + return 0; + } + + return utility::fileSize(m_filename); +} + +atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) { + if (!isOpen()) { + if (m_globalErr) + atError("File not open for reading"); + setError(); + return 0; + } + + if (m_blockSize <= 0) + return fread(buf, 1, len, m_fileHandle); + else { + atUint64 fs = utility::fileSize(m_filename); + if (m_offset >= fs) + return 0; + if (m_offset + len >= fs) + len = fs - m_offset; + + size_t block = m_offset / m_blockSize; + atUint64 cacheOffset = m_offset % m_blockSize; + atUint64 cacheSize; + atUint64 rem = len; + atUint8* dst = (atUint8*)buf; + + while (rem) { + if (block != m_curBlock) { + fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET); + fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle); + m_curBlock = (atInt32)block; + } + + cacheSize = rem; + if (cacheSize + cacheOffset > m_blockSize) + cacheSize = m_blockSize - cacheOffset; + + memmove(dst, m_cacheData.get() + cacheOffset, cacheSize); + dst += cacheSize; + rem -= cacheSize; + cacheOffset = 0; + ++block; } + m_offset += len; + return dst - (atUint8*)buf; + } } -void FileReader::setCacheSize(const atInt32 blockSize) -{ - m_blockSize = blockSize; +void FileReader::setCacheSize(const atInt32 blockSize) { + m_blockSize = blockSize; - if (m_blockSize > length()) - m_blockSize = (atInt32)length(); + if (m_blockSize > length()) + m_blockSize = (atInt32)length(); - m_curBlock = -1; - if (m_blockSize > 0) - m_cacheData.reset(new atUint8[m_blockSize]); + m_curBlock = -1; + if (m_blockSize > 0) + m_cacheData.reset(new atUint8[m_blockSize]); } -} // Athena +} // namespace athena::io diff --git a/src/athena/FileReaderWin32.cpp b/src/athena/FileReaderWin32.cpp index 904eb78..44b0b9a 100644 --- a/src/athena/FileReaderWin32.cpp +++ b/src/athena/FileReaderWin32.cpp @@ -1,233 +1,196 @@ #include "athena/FileReader.hpp" #include "win32_largefilewrapper.h" -namespace athena::io -{ +namespace athena::io { FileReader::FileReader(std::string_view filename, atInt32 cacheSize, bool globalErr) - : m_fileHandle(nullptr), - m_cacheData(nullptr), - m_offset(0), - m_globalErr(globalErr) -{ - m_filename = utility::utf8ToWide(filename); - open(); - setCacheSize(cacheSize); +: m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) { + m_filename = utility::utf8ToWide(filename); + open(); + setCacheSize(cacheSize); } FileReader::FileReader(std::wstring_view filename, atInt32 cacheSize, bool globalErr) - : m_fileHandle(nullptr), - m_cacheData(nullptr), - m_offset(0), - m_globalErr(globalErr) -{ - m_filename = filename; - open(); - setCacheSize(cacheSize); +: m_fileHandle(nullptr), m_cacheData(nullptr), m_offset(0), m_globalErr(globalErr) { + m_filename = filename; + open(); + setCacheSize(cacheSize); } -FileReader::~FileReader() -{ - if (isOpen()) - close(); +FileReader::~FileReader() { + if (isOpen()) + close(); } -void FileReader::open() -{ - int attempt = 0; - do - { +void FileReader::open() { + int attempt = 0; + do { #if WINDOWS_STORE - m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, - OPEN_EXISTING, nullptr); + m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); #else - m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, - nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, nullptr); #endif - } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100); + } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100); - if (m_fileHandle == INVALID_HANDLE_VALUE) - { - m_fileHandle = 0; - std::string _filename = filename(); - if (m_globalErr) - atError("File not found '%s'", _filename.c_str()); - setError(); - return; - } - - // reset error - m_hasError = false; -} - -void FileReader::close() -{ - if (!m_fileHandle) - { - if (m_globalErr) - atError("Cannot close an unopened stream"); - setError(); - return; - } - - CloseHandle(m_fileHandle); + if (m_fileHandle == INVALID_HANDLE_VALUE) { m_fileHandle = 0; + std::string _filename = filename(); + if (m_globalErr) + atError("File not found '%s'", _filename.c_str()); + setError(); return; + } + + // reset error + m_hasError = false; } -void FileReader::seek(atInt64 pos, SeekOrigin origin) -{ - if (!isOpen()) - return; +void FileReader::close() { + if (!m_fileHandle) { + if (m_globalErr) + atError("Cannot close an unopened stream"); + setError(); + return; + } - // check block pos