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 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) - { - LARGE_INTEGER li; - li.QuadPart = block * m_blockSize; - SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN); - ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr); - m_curBlock = (atInt32)block; - } - } - else - { - LARGE_INTEGER li; - li.QuadPart = pos; - if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) - { - if (m_globalErr) - atError("Unable to seek in file"); - setError(); - } - } + CloseHandle(m_fileHandle); + m_fileHandle = 0; + 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 - { - LARGE_INTEGER li = {}; - LARGE_INTEGER res; - SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); - return res.QuadPart; + size_t block = m_offset / m_blockSize; + if (block != m_curBlock) { + LARGE_INTEGER li; + li.QuadPart = block * m_blockSize; + SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN); + ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr); + m_curBlock = (atInt32)block; } + } else { + LARGE_INTEGER li; + li.QuadPart = pos; + if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) { + if (m_globalErr) + atError("Unable to seek in file"); + setError(); + } + } } -atUint64 FileReader::length() const -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open"); - return 0; - } +atUint64 FileReader::position() const { + if (!isOpen()) { + if (m_globalErr) + atError("File not open"); + return 0; + } + if (m_blockSize > 0) + return m_offset; + else { + LARGE_INTEGER li = {}; LARGE_INTEGER res; - GetFileSizeEx(m_fileHandle, &res); + SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); return res.QuadPart; + } } -atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open for reading"); - setError(); - return 0; - } +atUint64 FileReader::length() const { + if (!isOpen()) { + if (m_globalErr) + atError("File not open"); + return 0; + } - if (m_blockSize <= 0) - { - DWORD ret = 0; - ReadFile(m_fileHandle, buf, len, &ret, nullptr); - return ret; - } - else - { - LARGE_INTEGER fs; - GetFileSizeEx(m_fileHandle, &fs); - if (m_offset >= atUint64(fs.QuadPart)) - return 0; - if (m_offset + len >= atUint64(fs.QuadPart)) - len = fs.QuadPart - 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) - { - LARGE_INTEGER li; - li.QuadPart = block * m_blockSize; - SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN); - ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr); - 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; - } + LARGE_INTEGER res; + GetFileSizeEx(m_fileHandle, &res); + return res.QuadPart; } -void FileReader::setCacheSize(const atInt32 blockSize) -{ - m_blockSize = blockSize; +atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) { + if (!isOpen()) { + if (m_globalErr) + atError("File not open for reading"); + setError(); + return 0; + } - if (m_blockSize > length()) - m_blockSize = (atInt32)length(); + if (m_blockSize <= 0) { + DWORD ret = 0; + ReadFile(m_fileHandle, buf, len, &ret, nullptr); + return ret; + } else { + LARGE_INTEGER fs; + GetFileSizeEx(m_fileHandle, &fs); + if (m_offset >= atUint64(fs.QuadPart)) + return 0; + if (m_offset + len >= atUint64(fs.QuadPart)) + len = fs.QuadPart - m_offset; - m_curBlock = -1; - if (m_blockSize > 0) - m_cacheData.reset(new atUint8[m_blockSize]); + 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) { + LARGE_INTEGER li; + li.QuadPart = block * m_blockSize; + SetFilePointerEx(m_fileHandle, li, nullptr, FILE_BEGIN); + ReadFile(m_fileHandle, m_cacheData.get(), m_blockSize, nullptr, nullptr); + 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; + } } -} // Athena +void FileReader::setCacheSize(const atInt32 blockSize) { + m_blockSize = blockSize; + + if (m_blockSize > length()) + m_blockSize = (atInt32)length(); + + m_curBlock = -1; + if (m_blockSize > 0) + m_cacheData.reset(new atUint8[m_blockSize]); +} + +} // namespace athena::io diff --git a/src/athena/FileWriterGeneric.cpp b/src/athena/FileWriterGeneric.cpp index 384e203..7873123 100644 --- a/src/athena/FileWriterGeneric.cpp +++ b/src/athena/FileWriterGeneric.cpp @@ -1,32 +1,27 @@ #include "athena/FileWriter.hpp" -namespace athena::io -{ -void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin) -{ - switch (origin) - { - case SeekOrigin::Begin: - m_position = pos; - break; - case SeekOrigin::Current: - m_position += pos; - break; - case SeekOrigin::End: - break; - } +namespace athena::io { +void TransactionalFileWriter::seek(atInt64 pos, SeekOrigin origin) { + switch (origin) { + case SeekOrigin::Begin: + m_position = pos; + break; + case SeekOrigin::Current: + m_position += pos; + break; + case SeekOrigin::End: + break; + } } -void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len) -{ - atUint64 neededSz = m_position + len; - if (neededSz > m_deferredBuffer.size()) - { - m_deferredBuffer.reserve(neededSz * 2); - m_deferredBuffer.resize(neededSz); - } +void TransactionalFileWriter::writeUBytes(const atUint8* data, atUint64 len) { + atUint64 neededSz = m_position + len; + if (neededSz > m_deferredBuffer.size()) { + m_deferredBuffer.reserve(neededSz * 2); + m_deferredBuffer.resize(neededSz); + } - memmove(m_deferredBuffer.data() + m_position, data, len); - m_position += len; -} + memmove(m_deferredBuffer.data() + m_position, data, len); + m_position += len; } +} // namespace athena::io diff --git a/src/athena/FileWriterNix.cpp b/src/athena/FileWriterNix.cpp index afccad5..a1ca793 100644 --- a/src/athena/FileWriterNix.cpp +++ b/src/athena/FileWriterNix.cpp @@ -1,139 +1,114 @@ #include "athena/FileWriter.hpp" -#if __APPLE__ || __FreeBSD__ +#if __APPLE__ || __FreeBSD__ #include "osx_largefilewrapper.h" -#elif GEKKO || __SWITCH__ +#elif GEKKO || __SWITCH__ #include "gekko_support.h" #include "osx_largefilewrapper.h" #endif #include -namespace athena::io -{ +namespace athena::io { FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) - : m_fileHandle(NULL), - m_globalErr(globalErr) -{ +: m_fileHandle(NULL), m_globalErr(globalErr) { #if _WIN32 - m_filename = utility::utf8ToWide(filename); + m_filename = utility::utf8ToWide(filename); #else - m_filename = filename; + m_filename = filename; #endif - open(overwrite); + open(overwrite); } FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr) - : m_fileHandle(NULL), - m_globalErr(globalErr) -{ +: m_fileHandle(NULL), m_globalErr(globalErr) { #if _WIN32 - m_filename = filename; + m_filename = filename; #else - m_filename = utility::wideToUtf8(filename); + m_filename = utility::wideToUtf8(filename); #endif - open(overwrite); + open(overwrite); } -FileWriter::~FileWriter() -{ - if (isOpen()) - close(); +FileWriter::~FileWriter() { + if (isOpen()) + close(); } -void FileWriter::open(bool overwrite) -{ - if (overwrite) - { - std::string tmpFilename = m_filename + '~'; - m_fileHandle = fopen(tmpFilename.c_str(), "w+b"); - } - else - { - m_fileHandle = fopen(m_filename.c_str(), "a+b"); - if (m_fileHandle) - { - fclose(m_fileHandle); - m_fileHandle = fopen(m_filename.c_str(), "r+b"); - } - } - - if (!m_fileHandle) - { - if (m_globalErr) - atError("Unable to open file '%s'", filename().c_str()); - setError(); - return; - } - - // reset error - m_hasError = false; -} - -void FileWriter::close() -{ - if (!m_fileHandle) - { - if (m_globalErr) - atError("Cannot close an unopened stream"); - setError(); - return; - } - - fclose(m_fileHandle); - m_fileHandle = NULL; - +void FileWriter::open(bool overwrite) { + if (overwrite) { std::string tmpFilename = m_filename + '~'; + m_fileHandle = fopen(tmpFilename.c_str(), "w+b"); + } else { + m_fileHandle = fopen(m_filename.c_str(), "a+b"); + if (m_fileHandle) { + fclose(m_fileHandle); + m_fileHandle = fopen(m_filename.c_str(), "r+b"); + } + } + + if (!m_fileHandle) { + if (m_globalErr) + atError("Unable to open file '%s'", filename().c_str()); + setError(); + return; + } + + // reset error + m_hasError = false; +} + +void FileWriter::close() { + if (!m_fileHandle) { + if (m_globalErr) + atError("Cannot close an unopened stream"); + setError(); + return; + } + + fclose(m_fileHandle); + m_fileHandle = NULL; + + std::string tmpFilename = m_filename + '~'; #ifdef __SWITCH__ - /* Due to Horizon not being a fully POSIX compatible OS, we need to make sure the file *does not* exist before attempting to rename */ - unlink(m_filename.c_str()); + /* Due to Horizon not being a fully POSIX compatible OS, we need to make sure the file *does not* exist before + * attempting to rename */ + unlink(m_filename.c_str()); #endif - rename(tmpFilename.c_str(), m_filename.c_str()); + rename(tmpFilename.c_str(), m_filename.c_str()); } -void FileWriter::seek(atInt64 pos, SeekOrigin origin) -{ - if (!isOpen()) - { - if (m_globalErr) - atError("Unable to seek in file, not open"); - setError(); - return; - } +void FileWriter::seek(atInt64 pos, SeekOrigin origin) { + if (!isOpen()) { + if (m_globalErr) + atError("Unable to seek in file, not open"); + setError(); + return; + } - if (fseeko64(m_fileHandle, pos, (int)origin) != 0) - { - if (m_globalErr) - atError("Unable to seek in file"); - setError(); - } + if (fseeko64(m_fileHandle, pos, (int)origin) != 0) { + if (m_globalErr) + atError("Unable to seek in file"); + setError(); + } } -atUint64 FileWriter::position() const -{ - return ftello64(m_fileHandle); -} +atUint64 FileWriter::position() const { return ftello64(m_fileHandle); } -atUint64 FileWriter::length() const -{ - return utility::fileSize(m_filename); -} +atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } -void FileWriter::writeUBytes(const atUint8* data, atUint64 len) -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open for writing"); - setError(); - return; - } +void FileWriter::writeUBytes(const atUint8* data, atUint64 len) { + if (!isOpen()) { + if (m_globalErr) + atError("File not open for writing"); + setError(); + return; + } - if (fwrite(data, 1, len, m_fileHandle) != len) - { - if (m_globalErr) - atError("Unable to write to stream"); - setError(); - } + if (fwrite(data, 1, len, m_fileHandle) != len) { + if (m_globalErr) + atError("Unable to write to stream"); + setError(); + } } -} // Athena +} // namespace athena::io diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp index 1dcfdb1..de66e56 100644 --- a/src/athena/FileWriterWin32.cpp +++ b/src/athena/FileWriterWin32.cpp @@ -1,140 +1,114 @@ #include "athena/FileWriter.hpp" #include "win32_largefilewrapper.h" -namespace athena::io -{ +namespace athena::io { FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) - : m_fileHandle(0), - m_globalErr(globalErr) -{ - m_filename = utility::utf8ToWide(filename); - open(overwrite); +: m_fileHandle(0), m_globalErr(globalErr) { + m_filename = utility::utf8ToWide(filename); + open(overwrite); } FileWriter::FileWriter(std::wstring_view filename, bool overwrite, bool globalErr) - : m_fileHandle(0), - m_globalErr(globalErr) -{ - m_filename = filename; - open(overwrite); +: m_fileHandle(0), m_globalErr(globalErr) { + m_filename = filename; + open(overwrite); } -FileWriter::~FileWriter() -{ - if (isOpen()) - close(); +FileWriter::~FileWriter() { + if (isOpen()) + close(); } -void FileWriter::open(bool overwrite) -{ - int attempt = 0; - do - { - if (overwrite) - { - std::wstring tmpFilename = m_filename + L'~'; +void FileWriter::open(bool overwrite) { + int attempt = 0; + do { + if (overwrite) { + std::wstring tmpFilename = m_filename + L'~'; #if WINDOWS_STORE - m_fileHandle = CreateFile2(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, - CREATE_ALWAYS, nullptr); + m_fileHandle = CreateFile2(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr); #else - m_fileHandle = CreateFileW(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, - nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + m_fileHandle = CreateFileW(tmpFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, nullptr); #endif - } - else - { + } else { #if WINDOWS_STORE - m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, - OPEN_ALWAYS, nullptr); + m_fileHandle = CreateFile2(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_ALWAYS, nullptr); #else - m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, - nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + m_fileHandle = CreateFileW(m_filename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, nullptr); #endif - } - } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100); - - if (m_fileHandle == INVALID_HANDLE_VALUE) - { - m_fileHandle = 0; - if (m_globalErr) - atError("Unable to open file '%s'", filename().c_str()); - setError(); - return; } + } while (m_fileHandle == INVALID_HANDLE_VALUE && attempt++ < 100); - // reset error - m_hasError = false; -} - -void FileWriter::close() -{ - if (!m_fileHandle) - { - if (m_globalErr) - atError("Cannot close an unopened stream"); - setError(); - return; - } - - FlushFileBuffers(m_fileHandle); - CloseHandle(m_fileHandle); + if (m_fileHandle == INVALID_HANDLE_VALUE) { m_fileHandle = 0; + if (m_globalErr) + atError("Unable to open file '%s'", filename().c_str()); + setError(); + return; + } - std::wstring tmpFilename = m_filename + L'~'; - MoveFileExW(tmpFilename.c_str(), m_filename.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH); + // reset error + m_hasError = false; } -void FileWriter::seek(atInt64 pos, SeekOrigin origin) -{ - if (!isOpen()) - { - if (m_globalErr) - atError("Unable to seek in file, not open"); - setError(); - return; - } +void FileWriter::close() { + if (!m_fileHandle) { + if (m_globalErr) + atError("Cannot close an unopened stream"); + setError(); + return; + } - LARGE_INTEGER li; - li.QuadPart = pos; - if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) - { - if (m_globalErr) - atError("Unable to seek in file"); - setError(); - } + FlushFileBuffers(m_fileHandle); + CloseHandle(m_fileHandle); + m_fileHandle = 0; + + std::wstring tmpFilename = m_filename + L'~'; + MoveFileExW(tmpFilename.c_str(), m_filename.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH); } -atUint64 FileWriter::position() const -{ - LARGE_INTEGER li = {}; - LARGE_INTEGER res; - SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); - return res.QuadPart; +void FileWriter::seek(atInt64 pos, SeekOrigin origin) { + if (!isOpen()) { + if (m_globalErr) + atError("Unable to seek in file, not open"); + setError(); + return; + } + + LARGE_INTEGER li; + li.QuadPart = pos; + if (!SetFilePointerEx(m_fileHandle, li, nullptr, DWORD(origin))) { + if (m_globalErr) + atError("Unable to seek in file"); + setError(); + } } -atUint64 FileWriter::length() const -{ - return utility::fileSize(m_filename); +atUint64 FileWriter::position() const { + LARGE_INTEGER li = {}; + LARGE_INTEGER res; + SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); + return res.QuadPart; } -void FileWriter::writeUBytes(const atUint8* data, atUint64 len) -{ - if (!isOpen()) - { - if (m_globalErr) - atError("File not open for writing"); - setError(); - return; - } +atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } - DWORD ret = 0; - WriteFile(m_fileHandle, data, len, &ret, nullptr); - if (ret != len) - { - if (m_globalErr) - atError("Unable to write to stream"); - setError(); - } +void FileWriter::writeUBytes(const atUint8* data, atUint64 len) { + if (!isOpen()) { + if (m_globalErr) + atError("File not open for writing"); + setError(); + return; + } + + DWORD ret = 0; + WriteFile(m_fileHandle, data, len, &ret, nullptr); + if (ret != len) { + if (m_globalErr) + atError("Unable to write to stream"); + setError(); + } } -} // Athena +} // namespace athena::io diff --git a/src/athena/Global.cpp b/src/athena/Global.cpp index 3a37cd8..afecbf3 100644 --- a/src/athena/Global.cpp +++ b/src/athena/Global.cpp @@ -4,80 +4,69 @@ #include #include -std::ostream& operator<<(std::ostream& os, const athena::SeekOrigin& origin) -{ - switch (origin) - { - case athena::SeekOrigin::Begin: - os << "Begin"; - break; +std::ostream& operator<<(std::ostream& os, const athena::SeekOrigin& origin) { + switch (origin) { + case athena::SeekOrigin::Begin: + os << "Begin"; + break; - case athena::SeekOrigin::Current: - os << "Current"; - break; + case athena::SeekOrigin::Current: + os << "Current"; + break; - case athena::SeekOrigin::End: - os << "End"; - break; - } + case athena::SeekOrigin::End: + os << "End"; + break; + } - return os; + return os; } +std::ostream& operator<<(std::ostream& os, const athena::Endian& endian) { + switch (endian) { + case athena::Endian::Little: + os << "LittleEndian"; + break; -std::ostream& operator<<(std::ostream& os, const athena::Endian& endian) -{ - switch (endian) - { - case athena::Endian::Little: - os << "LittleEndian"; - break; + case athena::Endian::Big: + os << "BigEndian"; + break; + } - case athena::Endian::Big: - os << "BigEndian"; - break; - } - - return os; + return os; } +static void __defaultExceptionHandler(athena::error::Level level, const char* file, const char* function, int line, + const char* fmt, ...) { + std::string levelStr; + switch (level) { + case athena::error::Level::Warning: + levelStr = "[WARNING] "; + break; + case athena::error::Level::Error: + levelStr = "[ERROR ] "; + break; + case athena::error::Level::Fatal: + levelStr = "[FATAL ] "; + break; + default: + break; + } -static void __defaultExceptionHandler(athena::error::Level level, const char* file, const char* function, int line, const char* fmt, ...) -{ - std::string levelStr; - switch (level) - { - case athena::error::Level::Warning: - levelStr = "[WARNING] "; - break; - case athena::error::Level::Error: - levelStr = "[ERROR ] "; - break; - case athena::error::Level::Fatal: - levelStr = "[FATAL ] "; - break; - default: break; - } - - va_list vl; - va_start(vl, fmt); - std::string msg = athena::utility::vsprintf(fmt, vl); - va_end(vl); - std::cerr << levelStr << " " << file << " " << function << "(" << line << "): " << msg << std::endl; + va_list vl; + va_start(vl, fmt); + std::string msg = athena::utility::vsprintf(fmt, vl); + va_end(vl); + std::cerr << levelStr << " " << file << " " << function << "(" << line << "): " << msg << std::endl; } static atEXCEPTION_HANDLER g_atExceptionHandler = __defaultExceptionHandler; -atEXCEPTION_HANDLER atGetExceptionHandler() -{ - return g_atExceptionHandler; -} +atEXCEPTION_HANDLER atGetExceptionHandler() { return g_atExceptionHandler; } - -void atSetExceptionHandler(atEXCEPTION_HANDLER func) -{ - if (func) - g_atExceptionHandler = func; - else - g_atExceptionHandler = __defaultExceptionHandler; +void atSetExceptionHandler(atEXCEPTION_HANDLER func) { + if (func) + g_atExceptionHandler = func; + else + g_atExceptionHandler = __defaultExceptionHandler; } diff --git a/src/athena/MCFile.cpp b/src/athena/MCFile.cpp index 71b6462..6a44664 100644 --- a/src/athena/MCFile.cpp +++ b/src/athena/MCFile.cpp @@ -1,44 +1,37 @@ #include "athena/MCFile.hpp" -namespace athena -{ +namespace athena { const char MCFile::VERSION_EU_JP[33] = "AGBZELDA:THE MINISH CAP:ZELDA 3\0"; -const char MCFile::VERSION_US[33] = "AGBZELDA:THE MINISH CAP:ZELDA 5\0"; -MCFile::MCFile() -{ -} +const char MCFile::VERSION_US[33] = "AGBZELDA:THE MINISH CAP:ZELDA 5\0"; +MCFile::MCFile() {} // TODO: Rewrite this to be more optimized, the current solution takes quite a few cycles -atUint8* reverse(atUint8* data, atUint32 length) -{ - atUint32 a = 0; - atUint32 swap; +atUint8* reverse(atUint8* data, atUint32 length) { + atUint32 a = 0; + atUint32 swap; - for (; a < --length; a++) - { - swap = data[a]; - data[a] = data[length]; - data[length] = swap; - } + for (; a < --length; a++) { + swap = data[a]; + data[a] = data[length]; + data[length] = swap; + } - return data; + return data; } -atUint8* MCFile::unscramble(atUint8* data, atUint64 length) -{ - if (!data) - return nullptr; +atUint8* MCFile::unscramble(atUint8* data, atUint64 length) { + if (!data) + return nullptr; - for (atUint32 i = 0; i < length; i += 8) - { - atUint32 block1 = *(atUint32*)reverse((data + i), 4); - atUint32 block2 = *(atUint32*)reverse((data + i + 4), 4); - *(atUint32*)(data + i) = block2; - *(atUint32*)(data + i + 4) = block1; - } + for (atUint32 i = 0; i < length; i += 8) { + atUint32 block1 = *(atUint32*)reverse((data + i), 4); + atUint32 block2 = *(atUint32*)reverse((data + i + 4), 4); + *(atUint32*)(data + i) = block2; + *(atUint32*)(data + i + 4) = block1; + } - return data; + return data; } -} // zelda +} // namespace athena diff --git a/src/athena/MCFileReader.cpp b/src/athena/MCFileReader.cpp index b8f93ea..f333698 100644 --- a/src/athena/MCFileReader.cpp +++ b/src/athena/MCFileReader.cpp @@ -1,33 +1,23 @@ #include "athena/MCFileReader.hpp" #include "athena/MCFile.hpp" -namespace athena -{ +namespace athena { -namespace io -{ +namespace io { static const atUint32 SCRAMBLE_VALUE = 0x5A424741; -MCFileReader::MCFileReader(atUint8* data, atUint64 length) - : MemoryCopyReader(data, length) -{ +MCFileReader::MCFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {} + +MCFileReader::MCFileReader(const std::string& filename) : MemoryCopyReader(filename) {} + +MCFile* MCFileReader::readFile() { + bool isScrambled = readUint32() != SCRAMBLE_VALUE; + m_position = 0; + + if (isScrambled) + MCFile::unscramble(m_dataCopy.get(), m_length); + + return nullptr; } -MCFileReader::MCFileReader(const std::string& filename) - : MemoryCopyReader(filename) -{ -} - -MCFile* MCFileReader::readFile() -{ - bool isScrambled = readUint32() != SCRAMBLE_VALUE; - m_position = 0; - - if (isScrambled) - MCFile::unscramble(m_dataCopy.get(), m_length); - - return nullptr; -} - - -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/src/athena/MCFileWriter.cpp b/src/athena/MCFileWriter.cpp index c282ca6..3736545 100644 --- a/src/athena/MCFileWriter.cpp +++ b/src/athena/MCFileWriter.cpp @@ -1,49 +1,39 @@ #include "athena/MCFileWriter.hpp" -namespace athena::io -{ +namespace athena::io { -MCFileWriter::MCFileWriter(atUint8* data, atUint64 length) - : MemoryCopyWriter(data, length) -{ -} +MCFileWriter::MCFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {} -MCFileWriter::MCFileWriter(const std::string& filename) - : MemoryCopyWriter(filename) -{ -} +MCFileWriter::MCFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {} // TODO: Check the implementation, it seems to work fine, however it's not exactly correct, // looking at the disassembly, MC seems to do some weird checking that isn't being done with this solution // need to figure out what it's doing and whether it's relevant to the checksum. -atUint16 MCFileWriter::calculateSlotChecksum(atUint32 game) -{ - atUint16 first = calculateChecksum((m_data + 0x34 + (0x10 * game)), 4); - atUint16 second = calculateChecksum((m_data + 0x80 + (0x500 * game)), 0x500); +atUint16 MCFileWriter::calculateSlotChecksum(atUint32 game) { + atUint16 first = calculateChecksum((m_data + 0x34 + (0x10 * game)), 4); + atUint16 second = calculateChecksum((m_data + 0x80 + (0x500 * game)), 0x500); - first = (first + second) & 0xFFFF; - atUint16 result = first << 16; - second = ~first & 0xFFFF; - second += 1; - result += second; + first = (first + second) & 0xFFFF; + atUint16 result = first << 16; + second = ~first & 0xFFFF; + second += 1; + result += second; - return result; + return result; } -atUint16 MCFileWriter::calculateChecksum(atUint8* data, atUint32 length) -{ - atUint16 sum = 0; - int i = length; +atUint16 MCFileWriter::calculateChecksum(atUint8* data, atUint32 length) { + atUint16 sum = 0; + int i = length; - for (atUint32 j = 0; j < length; j += 2) - { - sum += *(atUint16*)(data + j) ^ i; - i -= 2; - } + for (atUint32 j = 0; j < length; j += 2) { + sum += *(atUint16*)(data + j) ^ i; + i -= 2; + } - sum &= 0xFFFF; + sum &= 0xFFFF; - return sum; + return sum; } -} // zelda +} // namespace athena::io diff --git a/src/athena/MCSlot.cpp b/src/athena/MCSlot.cpp index ab1247d..9557a3b 100644 --- a/src/athena/MCSlot.cpp +++ b/src/athena/MCSlot.cpp @@ -1,11 +1,8 @@ #include "athena/MCSlot.hpp" -namespace athena -{ +namespace athena { MCSlot::MCSlot(std::unique_ptr&& data, atUint32 length) - : ZQuestFile(ZQuestFile::MC, Endian::Little, std::move(data), length) -{ -} +: ZQuestFile(ZQuestFile::MC, Endian::Little, std::move(data), length) {} -} // Athena +} // namespace athena diff --git a/src/athena/MemoryReader.cpp b/src/athena/MemoryReader.cpp index 9bc9d1e..d7e57ef 100644 --- a/src/athena/MemoryReader.cpp +++ b/src/athena/MemoryReader.cpp @@ -14,184 +14,156 @@ #undef min #undef max -namespace athena::io -{ +namespace athena::io { MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr) - : m_data(data), - m_length(length), - m_position(0), - m_owns(takeOwnership), - m_globalErr(globalErr) -{ - if (!data) - { - if (m_globalErr) - atError("data cannot be NULL"); - setError(); - return; - } +: m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) { + if (!data) { + if (m_globalErr) + atError("data cannot be NULL"); + setError(); + return; + } } -MemoryReader::~MemoryReader() -{ - if (m_owns) - delete[] reinterpret_cast(m_data); +MemoryReader::~MemoryReader() { + if (m_owns) + delete[] reinterpret_cast(m_data); } -MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) - : MemoryReader(data, length, false) -{ - if (!data) - { - if (m_globalErr) - atError("data cannot be NULL"); - setError(); - return; +MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) : MemoryReader(data, length, false) { + if (!data) { + if (m_globalErr) + atError("data cannot be NULL"); + setError(); + return; + } + + m_dataCopy.reset(new atUint8[m_length]); + m_data = m_dataCopy.get(); + memmove(m_dataCopy.get(), data, m_length); +} + +void MemoryReader::seek(atInt64 position, SeekOrigin origin) { + switch (origin) { + case SeekOrigin::Begin: + if ((position < 0 || (atInt64)position > (atInt64)m_length)) { + if (m_globalErr) + atFatal("Position %0.8X outside stream bounds ", position); + m_position = m_length; + setError(); + return; } - m_dataCopy.reset(new atUint8[m_length]); - m_data = m_dataCopy.get(); - memmove(m_dataCopy.get(), data, m_length); -} + m_position = position; + break; -void MemoryReader::seek(atInt64 position, SeekOrigin origin) -{ - switch (origin) - { - case SeekOrigin::Begin: - if ((position < 0 || (atInt64)position > (atInt64)m_length)) - { - if (m_globalErr) - atFatal("Position %0.8X outside stream bounds ", position); - m_position = m_length; - setError(); - return; - } - - m_position = position; - break; - - case SeekOrigin::Current: - if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length)) - { - if (m_globalErr) - atFatal("Position %0.8X outside stream bounds ", position); - m_position = m_length; - setError(); - return; - } - - m_position += position; - break; - - case SeekOrigin::End: - if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) - { - if (m_globalErr) - atFatal("Position %0.8X outside stream bounds ", position); - m_position = m_length; - setError(); - return; - } - - m_position = m_length - position; - break; - } -} - -void MemoryReader::setData(const atUint8* data, atUint64 length, bool takeOwnership) -{ - if (m_owns) - delete[] static_cast(m_data); - m_data = (atUint8*)data; - m_length = length; - m_position = 0; - m_owns = takeOwnership; -} - -void MemoryCopyReader::setData(const atUint8* data, atUint64 length) -{ - m_dataCopy.reset(new atUint8[length]); - m_data = m_dataCopy.get(); - memmove(m_dataCopy.get(), data, length); - m_length = length; - m_position = 0; -} - -atUint8* MemoryReader::data() const -{ - atUint8* ret = new atUint8[m_length]; - memset(ret, 0, m_length); - memmove(ret, m_data, m_length); - return ret; -} - -atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) -{ - if (m_position >= m_length) - { - if (m_globalErr) - atFatal("Position %0.8X outside stream bounds ", m_position); - m_position = m_length; - setError(); - return 0; + case SeekOrigin::Current: + if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length)) { + if (m_globalErr) + atFatal("Position %0.8X outside stream bounds ", position); + m_position = m_length; + setError(); + return; } - length = std::min(length, m_length - m_position); - memmove(buf, reinterpret_cast(m_data) + m_position, length); - m_position += length; - return length; -} + m_position += position; + break; -void MemoryCopyReader::loadData() -{ - FILE* in; - atUint64 length; - in = fopen(m_filepath.c_str(), "rb"); - - if (!in) - { - if (m_globalErr) - atError("Unable to open file '%s'", m_filepath.c_str()); - setError(); - return; + case SeekOrigin::End: + if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) { + if (m_globalErr) + atFatal("Position %0.8X outside stream bounds ", position); + m_position = m_length; + setError(); + return; } - rewind(in); - - length = utility::fileSize(m_filepath); - m_dataCopy.reset(new atUint8[length]); - m_data = m_dataCopy.get(); - - atUint64 done = 0; - atUint64 blocksize = BLOCKSZ; - - do - { - if (blocksize > length - done) - blocksize = length - done; - - atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in); - - if (ret < 0) - { - if (m_globalErr) - atError("Error reading data from disk"); - setError(); - return; - } - else if (ret == 0) - break; - - done += ret; - - - } - while (done < length); - - fclose(in); - m_length = length; - m_position = 0; + m_position = m_length - position; + break; + } } +void MemoryReader::setData(const atUint8* data, atUint64 length, bool takeOwnership) { + if (m_owns) + delete[] static_cast(m_data); + m_data = (atUint8*)data; + m_length = length; + m_position = 0; + m_owns = takeOwnership; } + +void MemoryCopyReader::setData(const atUint8* data, atUint64 length) { + m_dataCopy.reset(new atUint8[length]); + m_data = m_dataCopy.get(); + memmove(m_dataCopy.get(), data, length); + m_length = length; + m_position = 0; +} + +atUint8* MemoryReader::data() const { + atUint8* ret = new atUint8[m_length]; + memset(ret, 0, m_length); + memmove(ret, m_data, m_length); + return ret; +} + +atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) { + if (m_position >= m_length) { + if (m_globalErr) + atFatal("Position %0.8X outside stream bounds ", m_position); + m_position = m_length; + setError(); + return 0; + } + + length = std::min(length, m_length - m_position); + memmove(buf, reinterpret_cast(m_data) + m_position, length); + m_position += length; + return length; +} + +void MemoryCopyReader::loadData() { + FILE* in; + atUint64 length; + in = fopen(m_filepath.c_str(), "rb"); + + if (!in) { + if (m_globalErr) + atError("Unable to open file '%s'", m_filepath.c_str()); + setError(); + return; + } + + rewind(in); + + length = utility::fileSize(m_filepath); + m_dataCopy.reset(new atUint8[length]); + m_data = m_dataCopy.get(); + + atUint64 done = 0; + atUint64 blocksize = BLOCKSZ; + + do { + if (blocksize > length - done) + blocksize = length - done; + + atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in); + + if (ret < 0) { + if (m_globalErr) + atError("Error reading data from disk"); + setError(); + return; + } else if (ret == 0) + break; + + done += ret; + + } while (done < length); + + fclose(in); + m_length = length; + m_position = 0; +} + +} // namespace athena::io diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index 1fd106b..36876ac 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -9,309 +9,267 @@ #include #endif // HW_RVL -namespace athena::io -{ +namespace athena::io { MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership) - : m_data((atUint8*)data), - m_length(length), - m_position(0), - m_bufferOwned(takeOwnership) -{ - if (!data) - { - atError("data cannot be NULL"); - setError(); - return; - } +: m_data((atUint8*)data), m_length(length), m_position(0), m_bufferOwned(takeOwnership) { + if (!data) { + atError("data cannot be NULL"); + setError(); + return; + } } -MemoryWriter::~MemoryWriter() -{ - if (m_bufferOwned) - delete m_data; - m_data = nullptr; - m_length = 0; +MemoryWriter::~MemoryWriter() { + if (m_bufferOwned) + delete m_data; + m_data = nullptr; + m_length = 0; } -MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) -{ - m_data = data; - m_length = length; - m_position = 0; - m_bufferOwned = false; +MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) { + m_data = data; + m_length = length; + m_position = 0; + m_bufferOwned = false; - if (length == 0) - { - atError("length cannot be 0"); - setError(); - return; - } - m_dataCopy.reset(new atUint8[length]); - m_data = m_dataCopy.get(); - if (data) - memmove(m_data, data, length); -} - -MemoryCopyWriter::MemoryCopyWriter(std::string_view filename) -{ - m_filepath = filename; - m_length = 0x10; - m_position = 0; - m_dataCopy.reset(new atUint8[m_length]); - m_data = m_dataCopy.get(); - m_bufferOwned = false; - - if (!m_data) - { - atError("Could not allocate memory!"); - setError(); - return; - } -} - -void MemoryWriter::seek(atInt64 position, SeekOrigin origin) -{ - switch (origin) - { - case SeekOrigin::Begin: - if (position < 0) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if ((atUint64)position > m_length) - { - atError("data exceeds available buffer space"); - setError(); - return; - } - - m_position = position; - break; - - case SeekOrigin::Current: - if ((((atInt64)m_position + position) < 0)) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if (m_position + position > m_length) - { - atError("data exceeds available buffer space"); - setError(); - return; - } - - m_position += position; - break; - - case SeekOrigin::End: - if (((atInt64)m_length - position) < 0) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if ((atUint64)position > m_length) - { - atError("data exceeds available buffer space"); - setError(); - return; - } - - m_position = m_length - position; - break; - } -} - -void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) -{ - switch (origin) - { - case SeekOrigin::Begin: - if (position < 0) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if ((atUint64)position > m_length) - resize(position); - - m_position = position; - break; - - case SeekOrigin::Current: - if ((((atInt64)m_position + position) < 0)) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if (m_position + position > m_length) - resize(m_position + position); - - m_position += position; - break; - - case SeekOrigin::End: - if (((atInt64)m_length - position) < 0) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if ((atUint64)position > m_length) - resize(position); - - m_position = m_length - position; - break; - } -} - -void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) -{ - if (m_bufferOwned) - delete m_data; - - m_data = (atUint8*)data; - m_length = length; - m_position = 0; - m_bufferOwned = takeOwnership; -} - -void MemoryCopyWriter::setData(const atUint8* data, atUint64 length) -{ - m_dataCopy.reset(new atUint8[length]); - m_data = m_dataCopy.get(); + if (length == 0) { + atError("length cannot be 0"); + setError(); + return; + } + m_dataCopy.reset(new atUint8[length]); + m_data = m_dataCopy.get(); + if (data) memmove(m_data, data, length); - m_length = length; - m_position = 0; - m_bufferOwned = false; } -atUint8* MemoryWriter::data() const -{ - atUint8* ret = new atUint8[m_length]; - memset(ret, 0, m_length); - memmove(ret, m_data, m_length); - return ret; +MemoryCopyWriter::MemoryCopyWriter(std::string_view filename) { + m_filepath = filename; + m_length = 0x10; + m_position = 0; + m_dataCopy.reset(new atUint8[m_length]); + m_data = m_dataCopy.get(); + m_bufferOwned = false; + + if (!m_data) { + atError("Could not allocate memory!"); + setError(); + return; + } } - -void MemoryWriter::save(std::string_view filename) -{ - if (filename.empty() && m_filepath.empty()) - { - atError("No file specified, cannot save."); - setError(); - return; +void MemoryWriter::seek(atInt64 position, SeekOrigin origin) { + switch (origin) { + case SeekOrigin::Begin: + if (position < 0) { + atError("Position outside stream bounds"); + setError(); + return; } - if (!filename.empty()) - m_filepath = filename; - - FILE* out = fopen(m_filepath.c_str(), "wb"); - - if (!out) - { - atError("Unable to open file '%s'", m_filepath.c_str()); - setError(); - return; + if ((atUint64)position > m_length) { + atError("data exceeds available buffer space"); + setError(); + return; } - atUint64 done = 0; - atUint64 blocksize = BLOCKSZ; + m_position = position; + break; - do - { - if (blocksize > m_length - done) - blocksize = m_length - done; - - atInt64 ret = fwrite(m_data + done, 1, blocksize, out); - - if (ret < 0) - { - atError("Error writing data to disk"); - setError(); - return; - } - else if (ret == 0) - break; - - done += blocksize; + case SeekOrigin::Current: + if ((((atInt64)m_position + position) < 0)) { + atError("Position outside stream bounds"); + setError(); + return; } - while (done < m_length); - fclose(out); + if (m_position + position > m_length) { + atError("data exceeds available buffer space"); + setError(); + return; + } + + m_position += position; + break; + + case SeekOrigin::End: + if (((atInt64)m_length - position) < 0) { + atError("Position outside stream bounds"); + setError(); + return; + } + + if ((atUint64)position > m_length) { + atError("data exceeds available buffer space"); + setError(); + return; + } + + m_position = m_length - position; + break; + } } -void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) -{ - if (!data) - { - atError("data cannnot be NULL"); - setError(); - return; +void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) { + switch (origin) { + case SeekOrigin::Begin: + if (position < 0) { + atError("Position outside stream bounds"); + setError(); + return; } - if (m_position + length > m_length) - { - atError("data length exceeds available buffer space"); - setError(); - return; + if ((atUint64)position > m_length) + resize(position); + + m_position = position; + break; + + case SeekOrigin::Current: + if ((((atInt64)m_position + position) < 0)) { + atError("Position outside stream bounds"); + setError(); + return; } - memmove(reinterpret_cast(m_data + m_position), data, length); + if (m_position + position > m_length) + resize(m_position + position); - m_position += length; + m_position += position; + break; + + case SeekOrigin::End: + if (((atInt64)m_length - position) < 0) { + atError("Position outside stream bounds"); + setError(); + return; + } + + if ((atUint64)position > m_length) + resize(position); + + m_position = m_length - position; + break; + } } -void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) -{ - if (!data) - { - atError("data cannnot be NULL"); - setError(); - return; - } +void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) { + if (m_bufferOwned) + delete m_data; - if (m_position + length > m_length) - resize(m_position + length); - - memmove(reinterpret_cast(m_data + m_position), data, length); - - m_position += length; + m_data = (atUint8*)data; + m_length = length; + m_position = 0; + m_bufferOwned = takeOwnership; } -void MemoryCopyWriter::resize(atUint64 newSize) -{ - if (newSize < m_length) - { - atError("New size cannot be less to the old size."); - return; - } - - // Allocate and copy new buffer - atUint8* newArray = new atUint8[newSize]; - memset(newArray, 0, newSize); - - if (m_dataCopy) - memmove(newArray, m_dataCopy.get(), m_length); - m_dataCopy.reset(newArray); - - // Swap the pointer and size out for the new ones. - m_data = newArray; - m_length = newSize; +void MemoryCopyWriter::setData(const atUint8* data, atUint64 length) { + m_dataCopy.reset(new atUint8[length]); + m_data = m_dataCopy.get(); + memmove(m_data, data, length); + m_length = length; + m_position = 0; + m_bufferOwned = false; } -} // Athena +atUint8* MemoryWriter::data() const { + atUint8* ret = new atUint8[m_length]; + memset(ret, 0, m_length); + memmove(ret, m_data, m_length); + return ret; +} + +void MemoryWriter::save(std::string_view filename) { + if (filename.empty() && m_filepath.empty()) { + atError("No file specified, cannot save."); + setError(); + return; + } + + if (!filename.empty()) + m_filepath = filename; + + FILE* out = fopen(m_filepath.c_str(), "wb"); + + if (!out) { + atError("Unable to open file '%s'", m_filepath.c_str()); + setError(); + return; + } + + atUint64 done = 0; + atUint64 blocksize = BLOCKSZ; + + do { + if (blocksize > m_length - done) + blocksize = m_length - done; + + atInt64 ret = fwrite(m_data + done, 1, blocksize, out); + + if (ret < 0) { + atError("Error writing data to disk"); + setError(); + return; + } else if (ret == 0) + break; + + done += blocksize; + } while (done < m_length); + + fclose(out); +} + +void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) { + if (!data) { + atError("data cannnot be NULL"); + setError(); + return; + } + + if (m_position + length > m_length) { + atError("data length exceeds available buffer space"); + setError(); + return; + } + + memmove(reinterpret_cast(m_data + m_position), data, length); + + m_position += length; +} + +void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) { + if (!data) { + atError("data cannnot be NULL"); + setError(); + return; + } + + if (m_position + length > m_length) + resize(m_position + length); + + memmove(reinterpret_cast(m_data + m_position), data, length); + + m_position += length; +} + +void MemoryCopyWriter::resize(atUint64 newSize) { + if (newSize < m_length) { + atError("New size cannot be less to the old size."); + return; + } + + // Allocate and copy new buffer + atUint8* newArray = new atUint8[newSize]; + memset(newArray, 0, newSize); + + if (m_dataCopy) + memmove(newArray, m_dataCopy.get(), m_length); + m_dataCopy.reset(newArray); + + // Swap the pointer and size out for the new ones. + m_data = newArray; + m_length = newSize; +} + +} // namespace athena::io diff --git a/src/athena/PHYSFSFileReader.cpp b/src/athena/PHYSFSFileReader.cpp index edbb1b7..3e64502 100644 --- a/src/athena/PHYSFSFileReader.cpp +++ b/src/athena/PHYSFSFileReader.cpp @@ -3,200 +3,132 @@ #include "athena/FileNotFoundException.hpp" #include "athena/IOException.hpp" -namespace athena::io -{ +namespace athena::io { -PHYSFSFileReader::PHYSFSFileReader(const std::string& path) - : m_path(path), - m_endian(Endian::LittleEndian) -{ - if (!PHYSFS_exists(m_path.c_str())) - THROW_FILE_NOT_FOUND_EXCEPTION(path); +PHYSFSFileReader::PHYSFSFileReader(const std::string& path) : m_path(path), m_endian(Endian::LittleEndian) { + if (!PHYSFS_exists(m_path.c_str())) + THROW_FILE_NOT_FOUND_EXCEPTION(path); - m_handle = PHYSFS_openRead(path.c_str()); - m_length = PHYSFS_fileLength(m_handle); + m_handle = PHYSFS_openRead(path.c_str()); + m_length = PHYSFS_fileLength(m_handle); } -atUint8* PHYSFSFileReader::data() -{ - return readUBytes(length()); +atUint8* PHYSFSFileReader::data() { return readUBytes(length()); } + +atUint64 PHYSFSFileReader::length() const { return m_length; } + +atUint64 PHYSFSFileReader::position() const { return PHYSFS_tell(m_handle); } + +bool PHYSFSFileReader::isOpen() const { return (m_handle != nullptr); } + +void PHYSFSFileReader::seek(atInt64 position, SeekOrigin origin) { + atInt64 curPos = PHYSFS_tell(m_handle); + + switch (origin) { + case SeekOrigin::Begin: + if ((position < 0 || (atInt64)position > (atInt64)m_length)) + THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + + PHYSFS_seek(m_handle, position); + break; + + case SeekOrigin::Current: + if ((((atInt64)curPos + position) < 0 || (curPos + position) > m_length)) + THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + + PHYSFS_seek(m_handle, curPos + position); + break; + + case SeekOrigin::End: + if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) + THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + + PHYSFS_seek(m_handle, m_length - position); + break; + } } -atUint64 PHYSFSFileReader::length() const -{ - return m_length; -} +atUint8 PHYSFSFileReader::readUByte() { + atUint8 val; -atUint64 PHYSFSFileReader::position() const -{ - return PHYSFS_tell(m_handle); -} - -bool PHYSFSFileReader::isOpen() const -{ - return (m_handle != nullptr); -} - -void PHYSFSFileReader::seek(atInt64 position, SeekOrigin origin) -{ - atInt64 curPos = PHYSFS_tell(m_handle); - - switch (origin) - { - case SeekOrigin::Begin: - if ((position < 0 || (atInt64)position > (atInt64)m_length)) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); - - PHYSFS_seek(m_handle, position); - break; - - case SeekOrigin::Current: - if ((((atInt64)curPos + position) < 0 || (curPos + position) > m_length)) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); - - PHYSFS_seek(m_handle, curPos + position); - break; - - case SeekOrigin::End: - if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); - - PHYSFS_seek(m_handle, m_length - position); - break; - } -} - -atUint8 PHYSFSFileReader::readUByte() -{ - atUint8 val; - - if (!PHYSFS_read(m_handle, &val, 1, 1)) - THROW_IO_EXCEPTION("Position outside stream bounds"); - - return val; -} - -atInt8 PHYSFSFileReader::readByte() -{ - return readUByte(); -} - -atUint8* PHYSFSFileReader::readUBytes(atUint64 length) -{ - atUint8* data = new atUint8[length]; - - if (PHYSFS_read(m_handle, data, 1, length) == length) - return data; - - delete[] data; + if (!PHYSFS_read(m_handle, &val, 1, 1)) THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; } -atInt8* PHYSFSFileReader::readBytes(atUint64 length) -{ - return (atInt8*)readUBytes(length); +atInt8 PHYSFSFileReader::readByte() { return readUByte(); } + +atUint8* PHYSFSFileReader::readUBytes(atUint64 length) { + atUint8* data = new atUint8[length]; + + if (PHYSFS_read(m_handle, data, 1, length) == length) + return data; + + delete[] data; + THROW_IO_EXCEPTION("Position outside stream bounds"); } -atUint16 PHYSFSFileReader::readUint16() -{ - atUint16 val; +atInt8* PHYSFSFileReader::readBytes(atUint64 length) { return (atInt8*)readUBytes(length); } - if (m_endian == Endian::BigEndian) - { - if (!PHYSFS_readUBE16(m_handle, &val)) - THROW_IO_EXCEPTION("Position outside stream bounds"); - } - else if (!PHYSFS_readULE16(m_handle, &val)) - THROW_IO_EXCEPTION("Position outside stream bounds"); +atUint16 PHYSFSFileReader::readUint16() { + atUint16 val; - return val; + if (m_endian == Endian::BigEndian) { + if (!PHYSFS_readUBE16(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + } else if (!PHYSFS_readULE16(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; } -atInt16 PHYSFSFileReader::readInt16() -{ - return readUint16(); +atInt16 PHYSFSFileReader::readInt16() { return readUint16(); } + +atUint32 PHYSFSFileReader::readUint32() { + atUint32 val; + + if (m_endian == Endian::BigEndian) { + if (!PHYSFS_readUBE32(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + } else if (!PHYSFS_readULE32(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; } -atUint32 PHYSFSFileReader::readUint32() -{ - atUint32 val; +atInt32 PHYSFSFileReader::readInt32() { return readUint32(); } - if (m_endian == Endian::BigEndian) - { - if (!PHYSFS_readUBE32(m_handle, &val)) - THROW_IO_EXCEPTION("Position outside stream bounds"); - } - else if (!PHYSFS_readULE32(m_handle, &val)) - THROW_IO_EXCEPTION("Position outside stream bounds"); +atUint64 PHYSFSFileReader::readUint64() { + atUint64 val; - return val; + if (m_endian == Endian::BigEndian) { + if (!PHYSFS_readUBE64(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + } else if (!PHYSFS_readUBE64(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; } -atInt32 PHYSFSFileReader::readInt32() -{ - return readUint32(); -} +atInt64 PHYSFSFileReader::readInt64() { return readUint64(); } -atUint64 PHYSFSFileReader::readUint64() -{ - atUint64 val; +double PHYSFSFileReader::readDouble() { return static_cast(readUint64()); } - if (m_endian == Endian::BigEndian) - { - if (!PHYSFS_readUBE64(m_handle, &val)) - THROW_IO_EXCEPTION("Position outside stream bounds"); - } - else if (!PHYSFS_readUBE64(m_handle, &val)) - THROW_IO_EXCEPTION("Position outside stream bounds"); +float PHYSFSFileReader::readFloat() { return static_cast(readUint32()); } - return val; -} +bool PHYSFSFileReader::readBool() { return (readByte() != 0); } -atInt64 PHYSFSFileReader::readInt64() -{ - return readUint64(); -} +bool PHYSFSFileReader::atEnd() const { return PHYSFS_eof(m_handle); } -double PHYSFSFileReader::readDouble() -{ - return static_cast(readUint64()); -} +void PHYSFSFileReader::setEndian(Endian endian) { m_endian = endian; } -float PHYSFSFileReader::readFloat() -{ - return static_cast(readUint32()); -} +Endian PHYSFSFileReader::endian() const { return m_endian; } -bool PHYSFSFileReader::readBool() -{ - return (readByte() != 0); -} +bool PHYSFSFileReader::isBigEndian() const { return m_endian == Endian::BigEndian; } -bool PHYSFSFileReader::atEnd() const -{ - return PHYSFS_eof(m_handle); -} +bool PHYSFSFileReader::isLittleEndian() const { return m_endian == Endian::LittleEndian; } -void PHYSFSFileReader::setEndian(Endian endian) -{ - m_endian = endian; -} - -Endian PHYSFSFileReader::endian() const -{ - return m_endian; -} - -bool PHYSFSFileReader::isBigEndian() const -{ - return m_endian == Endian::BigEndian; -} - -bool PHYSFSFileReader::isLittleEndian() const -{ - return m_endian == Endian::LittleEndian; -} - -} +} // namespace athena::io #endif diff --git a/src/athena/SkywardSwordFile.cpp b/src/athena/SkywardSwordFile.cpp index daa7c5b..eba259b 100644 --- a/src/athena/SkywardSwordFile.cpp +++ b/src/athena/SkywardSwordFile.cpp @@ -1,58 +1,35 @@ #include "athena/SkywardSwordFile.hpp" #include "athena/SkywardSwordQuest.hpp" -namespace athena -{ +namespace athena { -SkywardSwordFile::SkywardSwordFile() - : m_numQuests(0) -{ +SkywardSwordFile::SkywardSwordFile() : m_numQuests(0) {} + +SkywardSwordFile::SkywardSwordFile(std::vector quests) : m_numQuests(0) { m_quests = quests; } + +SkywardSwordFile::~SkywardSwordFile() {} + +void SkywardSwordFile::addQuest(athena::SkywardSwordQuest* q) { + // Do not allow more than 3 quests + if (m_quests.size() >= 3) + return; + + m_quests.push_back(q); } -SkywardSwordFile::SkywardSwordFile(std::vector quests) - : m_numQuests(0) -{ - m_quests = quests; +SkywardSwordQuest* SkywardSwordFile::quest(atUint32 id) { + if (id > m_quests.size() - 1) { + atWarning("index out of range"); + return nullptr; + } + + return m_quests[id]; } -SkywardSwordFile::~SkywardSwordFile() -{ -} +std::vector SkywardSwordFile::questList() const { return m_quests; } -void SkywardSwordFile::addQuest(athena::SkywardSwordQuest* q) -{ - // Do not allow more than 3 quests - if (m_quests.size() >= 3) - return; +void SkywardSwordFile::setRegion(Region region) { m_region = region; } - m_quests.push_back(q); -} +Region SkywardSwordFile::region() const { return m_region; } -SkywardSwordQuest* SkywardSwordFile::quest(atUint32 id) -{ - if (id > m_quests.size() - 1) - { - atWarning("index out of range"); - return nullptr; - } - - return m_quests[id]; -} - -std::vector SkywardSwordFile::questList() const -{ - return m_quests; -} - -void SkywardSwordFile::setRegion(Region region) -{ - m_region = region; -} - -Region SkywardSwordFile::region() const -{ - return m_region; -} - - -} // zelda +} // namespace athena diff --git a/src/athena/SkywardSwordFileReader.cpp b/src/athena/SkywardSwordFileReader.cpp index 0080a29..67b81ba 100644 --- a/src/athena/SkywardSwordFileReader.cpp +++ b/src/athena/SkywardSwordFileReader.cpp @@ -3,64 +3,56 @@ #include "athena/SkywardSwordQuest.hpp" #include -namespace athena::io -{ +namespace athena::io { -SkywardSwordFileReader::SkywardSwordFileReader(atUint8* data, atUint64 length) - : MemoryCopyReader(data, length) -{ - setEndian(Endian::Big); +SkywardSwordFileReader::SkywardSwordFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) { + setEndian(Endian::Big); } -SkywardSwordFileReader::SkywardSwordFileReader(const std::string& filename) - : MemoryCopyReader(filename) -{ - setEndian(Endian::Big); +SkywardSwordFileReader::SkywardSwordFileReader(const std::string& filename) : MemoryCopyReader(filename) { + setEndian(Endian::Big); } -SkywardSwordFile* SkywardSwordFileReader::read() -{ - SkywardSwordFile* file = NULL; +SkywardSwordFile* SkywardSwordFileReader::read() { + SkywardSwordFile* file = NULL; - if (length() != 0xFBE0) - { - atError("File not the expected size of 0xFBE0"); - return nullptr; - } + if (length() != 0xFBE0) { + atError("File not the expected size of 0xFBE0"); + return nullptr; + } - atUint32 magic = readUint32(); + atUint32 magic = readUint32(); - if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) - { - atError("Not a valid Skyward Sword save file"); - return nullptr; - } + if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) { + atError("Not a valid Skyward Sword save file"); + return nullptr; + } - seek(0x01C, SeekOrigin::Begin); - atUint32 headerSize = readUint32(); // Seems to be (headerSize - 1) + seek(0x01C, SeekOrigin::Begin); + atUint32 headerSize = readUint32(); // Seems to be (headerSize - 1) - if (headerSize != 0x1D) - { - atError("Invalid header size, Corrupted data?"); - return nullptr; - } + if (headerSize != 0x1D) { + atError("Invalid header size, Corrupted data?"); + return nullptr; + } - // Time to read in each slot - file = new SkywardSwordFile; - file->setRegion((magic == SkywardSwordFile::USMagic ? Region::NTSC : (magic == SkywardSwordFile::JAMagic ? Region::NTSCJ : Region::PAL))); + // Time to read in each slot + file = new SkywardSwordFile; + file->setRegion((magic == SkywardSwordFile::USMagic + ? Region::NTSC + : (magic == SkywardSwordFile::JAMagic ? Region::NTSCJ : Region::PAL))); - for (int i = 0; i < 3; i++) - { - SkywardSwordQuest* q = new SkywardSwordQuest(readUBytes(0x53C0), 0x53C0); - atUint64 pos = position(); - // seek to the skip data for this particular quest - seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); - q->setSkipData(readUBytes(0x24)); - seek(pos, SeekOrigin::Begin); - file->addQuest(q); - } + for (int i = 0; i < 3; i++) { + SkywardSwordQuest* q = new SkywardSwordQuest(readUBytes(0x53C0), 0x53C0); + atUint64 pos = position(); + // seek to the skip data for this particular quest + seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); + q->setSkipData(readUBytes(0x24)); + seek(pos, SeekOrigin::Begin); + file->addQuest(q); + } - return file; + return file; } -} // zelda +} // namespace athena::io diff --git a/src/athena/SkywardSwordFileWriter.cpp b/src/athena/SkywardSwordFileWriter.cpp index 4b35449..d76d93e 100644 --- a/src/athena/SkywardSwordFileWriter.cpp +++ b/src/athena/SkywardSwordFileWriter.cpp @@ -2,62 +2,54 @@ #include "athena/SkywardSwordFile.hpp" #include "athena/SkywardSwordQuest.hpp" -namespace athena::io -{ +namespace athena::io { -SkywardSwordFileWriter::SkywardSwordFileWriter(atUint8* data, atUint64 len) - : MemoryCopyWriter(data, len) -{ - setEndian(Endian::Big); +SkywardSwordFileWriter::SkywardSwordFileWriter(atUint8* data, atUint64 len) : MemoryCopyWriter(data, len) { + setEndian(Endian::Big); } -SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string& filename) - : MemoryCopyWriter(filename) -{ - setEndian(Endian::Big); +SkywardSwordFileWriter::SkywardSwordFileWriter(const std::string& filename) : MemoryCopyWriter(filename) { + setEndian(Endian::Big); } -void SkywardSwordFileWriter::write(SkywardSwordFile* file) -{ - if (!file) - { - atError("file cannot be NULL"); - return; +void SkywardSwordFileWriter::write(SkywardSwordFile* file) { + if (!file) { + atError("file cannot be NULL"); + return; + } + + atUint32 magic = (file->region() == Region::NTSC + ? SkywardSwordFile::USMagic + : (file->region() == Region::NTSCJ ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic)); + + writeUint32(magic); + seek(0x1C, SeekOrigin::Begin); + writeUint32(0x1D); + + std::vector quests = file->questList(); + int i = 0; + + for (SkywardSwordQuest* q : quests) { + if (q->length() != 0x53C0) { + atError("q->data() not 0x53C0 bytes in length"); + return; } - atUint32 magic = (file->region() == Region::NTSC ? SkywardSwordFile::USMagic : - (file->region() == Region::NTSCJ ? SkywardSwordFile::JAMagic : SkywardSwordFile::EUMagic)); + // Update the checksums + q->fixChecksums(); + // Write the save data + writeUBytes(q->data(), q->length()); + atUint64 pos = position(); + // Write the slots skip data + seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); + writeUBytes(q->skipData(), 0x24); + seek(pos, SeekOrigin::Begin); + i++; + } - writeUint32(magic); - seek(0x1C, SeekOrigin::Begin); - writeUint32(0x1D); - - std::vector quests = file->questList(); - int i = 0; - - for (SkywardSwordQuest* q : quests) - { - if (q->length() != 0x53C0) - { - atError("q->data() not 0x53C0 bytes in length"); - return; - } - - // Update the checksums - q->fixChecksums(); - // Write the save data - writeUBytes(q->data(), q->length()); - atUint64 pos = position(); - // Write the slots skip data - seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); - writeUBytes(q->skipData(), 0x24); - seek(pos, SeekOrigin::Begin); - i++; - } - - // write those padding bytes - seek(0xFBE0, SeekOrigin::Begin); - save(); + // write those padding bytes + seek(0xFBE0, SeekOrigin::Begin); + save(); } -} // zelda +} // namespace athena::io diff --git a/src/athena/SkywardSwordQuest.cpp b/src/athena/SkywardSwordQuest.cpp index ab60b4b..f9604d2 100644 --- a/src/athena/SkywardSwordQuest.cpp +++ b/src/athena/SkywardSwordQuest.cpp @@ -4,260 +4,207 @@ #include "utf8proc.h" #include -namespace athena -{ +namespace athena { -namespace priv -{ -static const atUint32 NAME_OFFSET = 0x08D4; -static const atUint32 RUPEE_COUNT_OFFSET = 0x0A5E; -static const atUint32 AMMO_COUNT_OFFSET = 0x0A60; -static const atUint32 MAX_HP_OFFSET = 0x5302; -static const atUint32 SPAWN_HP_OFFSET = 0x5304; -static const atUint32 CURRENT_HP_OFFSET = 0x5306; -static const atUint32 ROOM_ID_OFFSET = 0x5309; -static const atUint32 CURRENT_LOCATION_OFFSET = 0x531C; -static const atUint32 CURRENT_AREA_OFFSET = 0x533C; +namespace priv { +static const atUint32 NAME_OFFSET = 0x08D4; +static const atUint32 RUPEE_COUNT_OFFSET = 0x0A5E; +static const atUint32 AMMO_COUNT_OFFSET = 0x0A60; +static const atUint32 MAX_HP_OFFSET = 0x5302; +static const atUint32 SPAWN_HP_OFFSET = 0x5304; +static const atUint32 CURRENT_HP_OFFSET = 0x5306; +static const atUint32 ROOM_ID_OFFSET = 0x5309; +static const atUint32 CURRENT_LOCATION_OFFSET = 0x531C; +static const atUint32 CURRENT_AREA_OFFSET = 0x533C; static const atUint32 CURRENT_LOCATION_COPY_OFFSET = 0x535C; -static const atUint32 CHECKSUM_OFFSET = 0x53BC; -static const atUint32 ISNEW_OFFSET = 0x53AD; +static const atUint32 CHECKSUM_OFFSET = 0x53BC; +static const atUint32 ISNEW_OFFSET = 0x53AD; -static const atUint32 SKIP_CHECKSUM_OFFSET = 0x20; -} +static const atUint32 SKIP_CHECKSUM_OFFSET = 0x20; +} // namespace priv -union AmmoValues -{ - struct - { - atUint32 arrows : 7; - atUint32 bombs : 7; - atUint32 : 9; - atUint32 seeds : 7; - atUint32 : 2; - }; - atUint32 value; +union AmmoValues { + struct { + atUint32 arrows : 7; + atUint32 bombs : 7; + atUint32 : 9; + atUint32 seeds : 7; + atUint32 : 2; + }; + atUint32 value; }; SkywardSwordQuest::SkywardSwordQuest(std::unique_ptr&& data, atUint32 len) - : ZQuestFile(ZQuestFile::SS, Endian::Big, std::move(data), len) -{ -} +: ZQuestFile(ZQuestFile::SS, Endian::Big, std::move(data), len) {} -void SkywardSwordQuest::setSkipData(std::unique_ptr&& data) -{ - m_skipData = std::move(data); -} +void SkywardSwordQuest::setSkipData(std::unique_ptr&& data) { m_skipData = std::move(data); } -atUint8* SkywardSwordQuest::skipData() const -{ - return m_skipData.get(); -} +atUint8* SkywardSwordQuest::skipData() const { return m_skipData.get(); } -void SkywardSwordQuest::setPlayerName(const std::string& name) -{ - if (name.length() > 8) - atDebug("WARNING: name cannot be greater than 8 characters, automatically truncating"); +void SkywardSwordQuest::setPlayerName(const std::string& name) { + if (name.length() > 8) + atDebug("WARNING: name cannot be greater than 8 characters, automatically truncating"); - const utf8proc_uint8_t* buf = reinterpret_cast(name.c_str()); - for (atUint32 i = 0; i < 8; i++) - { - atUint16& c = *(atUint16*)(m_data.get() + priv::NAME_OFFSET + (i * 2)); + const utf8proc_uint8_t* buf = reinterpret_cast(name.c_str()); + for (atUint32 i = 0; i < 8; i++) { + atUint16& c = *(atUint16*)(m_data.get() + priv::NAME_OFFSET + (i * 2)); - if (!*buf) - { - c = 0; - continue; - } - - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) - { - atError("invalid UTF-8 string"); - return; - } - buf += len; - c = atUint16(wc); - utility::BigUint16(c); - } -} - -std::string SkywardSwordQuest::playerName() const -{ - std::string val; - - for (atUint32 i = 0; i < 8; i++) - { - atUint16 c = *(atUint16*)(m_data.get() + priv::NAME_OFFSET + (i * 2)); - - if (c == 0) - break; - - utility::BigUint16(c); - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t cs = utf8proc_encode_char(utf8proc_int32_t(c), mb); - if (cs) - val.append(reinterpret_cast(mb), cs); + if (!*buf) { + c = 0; + continue; } - return val; -} - -void SkywardSwordQuest::setRupeeCount(atUint16 value) -{ - atUint16& tmp = *(atUint16*)(m_data.get() + priv::RUPEE_COUNT_OFFSET); - tmp = value; - utility::BigUint16(tmp); -} - -atUint16 SkywardSwordQuest::rupeeCount() -{ - atUint16 ret = *(atUint16*)(m_data.get() + priv::RUPEE_COUNT_OFFSET); - return utility::BigUint16(ret); -} - -void SkywardSwordQuest::setAmmoCount(SkywardSwordQuest::AmmoType type, atUint32 count) -{ - AmmoValues& values = *(AmmoValues*)(m_data.get() + priv::AMMO_COUNT_OFFSET); - utility::BigUint32(values.value); - - switch (type) - { - case Arrows: - values.arrows = count; - break; - - case Bombs: - values.bombs = count; - break; - - case Seeds: - values.seeds = count; - break; + utf8proc_int32_t wc; + utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); + if (len < 0) { + atError("invalid UTF-8 string"); + return; } - - utility::BigUint32(values.value); + buf += len; + c = atUint16(wc); + utility::BigUint16(c); + } } -atUint32 SkywardSwordQuest::ammoCount(AmmoType type) -{ - AmmoValues values = *(AmmoValues*)(m_data.get() + priv::AMMO_COUNT_OFFSET); - utility::BigUint32(values.value); +std::string SkywardSwordQuest::playerName() const { + std::string val; - switch (type) - { - case Arrows: - return values.arrows; + for (atUint32 i = 0; i < 8; i++) { + atUint16 c = *(atUint16*)(m_data.get() + priv::NAME_OFFSET + (i * 2)); - case Bombs: - return values.bombs; + if (c == 0) + break; - case Seeds: - return values.seeds; + utility::BigUint16(c); + utf8proc_uint8_t mb[4]; + utf8proc_ssize_t cs = utf8proc_encode_char(utf8proc_int32_t(c), mb); + if (cs) + val.append(reinterpret_cast(mb), cs); + } - default: - return 0; - } + return val; } -void SkywardSwordQuest::setMaxHP(atUint16 val) -{ - *(atUint16*)(m_data.get() + priv::MAX_HP_OFFSET) = utility::BigUint16(val); +void SkywardSwordQuest::setRupeeCount(atUint16 value) { + atUint16& tmp = *(atUint16*)(m_data.get() + priv::RUPEE_COUNT_OFFSET); + tmp = value; + utility::BigUint16(tmp); } -atUint16 SkywardSwordQuest::maxHP() -{ - atUint16 ret = *(atUint16*)(m_data.get() + priv::MAX_HP_OFFSET); - return utility::BigUint16(ret); +atUint16 SkywardSwordQuest::rupeeCount() { + atUint16 ret = *(atUint16*)(m_data.get() + priv::RUPEE_COUNT_OFFSET); + return utility::BigUint16(ret); } -float SkywardSwordQuest::maxHearts() -{ - return (maxHP() / 4.f); +void SkywardSwordQuest::setAmmoCount(SkywardSwordQuest::AmmoType type, atUint32 count) { + AmmoValues& values = *(AmmoValues*)(m_data.get() + priv::AMMO_COUNT_OFFSET); + utility::BigUint32(values.value); + + switch (type) { + case Arrows: + values.arrows = count; + break; + + case Bombs: + values.bombs = count; + break; + + case Seeds: + values.seeds = count; + break; + } + + utility::BigUint32(values.value); } -void SkywardSwordQuest::setSpawnHP(atUint16 val) -{ - *(atUint16*)(m_data.get() + priv::SPAWN_HP_OFFSET) = utility::BigUint16(val); +atUint32 SkywardSwordQuest::ammoCount(AmmoType type) { + AmmoValues values = *(AmmoValues*)(m_data.get() + priv::AMMO_COUNT_OFFSET); + utility::BigUint32(values.value); + + switch (type) { + case Arrows: + return values.arrows; + + case Bombs: + return values.bombs; + + case Seeds: + return values.seeds; + + default: + return 0; + } } -atUint16 SkywardSwordQuest::spawnHP() -{ - atUint16 ret = *(atUint16*)(m_data.get() + priv::SPAWN_HP_OFFSET); - return utility::BigUint16(ret); +void SkywardSwordQuest::setMaxHP(atUint16 val) { + *(atUint16*)(m_data.get() + priv::MAX_HP_OFFSET) = utility::BigUint16(val); } -float SkywardSwordQuest::spawnHearts() -{ - return (spawnHP() / 4.f); +atUint16 SkywardSwordQuest::maxHP() { + atUint16 ret = *(atUint16*)(m_data.get() + priv::MAX_HP_OFFSET); + return utility::BigUint16(ret); } -void SkywardSwordQuest::setCurrentHP(atUint16 val) -{ - *(atUint16*)(m_data.get() + priv::CURRENT_HP_OFFSET) = utility::BigUint16(val); +float SkywardSwordQuest::maxHearts() { return (maxHP() / 4.f); } + +void SkywardSwordQuest::setSpawnHP(atUint16 val) { + *(atUint16*)(m_data.get() + priv::SPAWN_HP_OFFSET) = utility::BigUint16(val); } -atUint16 SkywardSwordQuest::currentHP() -{ - atUint16 ret = *(atUint16*)(m_data.get() + priv::CURRENT_HP_OFFSET); - return utility::BigUint16(ret); +atUint16 SkywardSwordQuest::spawnHP() { + atUint16 ret = *(atUint16*)(m_data.get() + priv::SPAWN_HP_OFFSET); + return utility::BigUint16(ret); } -float SkywardSwordQuest::currentHearts() -{ - return (currentHP() / 4.f); +float SkywardSwordQuest::spawnHearts() { return (spawnHP() / 4.f); } + +void SkywardSwordQuest::setCurrentHP(atUint16 val) { + *(atUint16*)(m_data.get() + priv::CURRENT_HP_OFFSET) = utility::BigUint16(val); } -std::string SkywardSwordQuest::currentLocation() -{ - return std::string((char*)m_data.get() + priv::CURRENT_LOCATION_OFFSET); +atUint16 SkywardSwordQuest::currentHP() { + atUint16 ret = *(atUint16*)(m_data.get() + priv::CURRENT_HP_OFFSET); + return utility::BigUint16(ret); } -std::string SkywardSwordQuest::currentArea() -{ - return std::string((char*)m_data.get() + priv::CURRENT_AREA_OFFSET); +float SkywardSwordQuest::currentHearts() { return (currentHP() / 4.f); } + +std::string SkywardSwordQuest::currentLocation() { + return std::string((char*)m_data.get() + priv::CURRENT_LOCATION_OFFSET); } -std::string SkywardSwordQuest::currentLocationCopy() -{ - return std::string((char*)m_data.get() + priv::CURRENT_LOCATION_COPY_OFFSET); +std::string SkywardSwordQuest::currentArea() { return std::string((char*)m_data.get() + priv::CURRENT_AREA_OFFSET); } + +std::string SkywardSwordQuest::currentLocationCopy() { + return std::string((char*)m_data.get() + priv::CURRENT_LOCATION_COPY_OFFSET); } -atUint32 SkywardSwordQuest::slotChecksum() -{ - atUint32 ret = *(atUint32*)(m_data.get() + priv::CHECKSUM_OFFSET); - utility::BigUint32(ret); +atUint32 SkywardSwordQuest::slotChecksum() { + atUint32 ret = *(atUint32*)(m_data.get() + priv::CHECKSUM_OFFSET); + utility::BigUint32(ret); - return ret; + return ret; } -atUint32 SkywardSwordQuest::skipChecksum() -{ - atUint32 ret = *(atUint32*)(m_skipData.get() + priv::SKIP_CHECKSUM_OFFSET); - utility::BigUint32(ret); +atUint32 SkywardSwordQuest::skipChecksum() { + atUint32 ret = *(atUint32*)(m_skipData.get() + priv::SKIP_CHECKSUM_OFFSET); + utility::BigUint32(ret); - return ret; + return ret; } -void SkywardSwordQuest::fixChecksums() -{ - atUint32 checksum = checksums::crc32(m_data.get(), priv::CHECKSUM_OFFSET); - utility::BigUint32(checksum); - *(atUint32*)(m_data.get() + priv::CHECKSUM_OFFSET) = checksum; +void SkywardSwordQuest::fixChecksums() { + atUint32 checksum = checksums::crc32(m_data.get(), priv::CHECKSUM_OFFSET); + utility::BigUint32(checksum); + *(atUint32*)(m_data.get() + priv::CHECKSUM_OFFSET) = checksum; - checksum = checksums::crc32(m_skipData.get(), priv::SKIP_CHECKSUM_OFFSET); - utility::BigUint32(checksum); - *(atUint32*)(m_skipData.get() + priv::SKIP_CHECKSUM_OFFSET) = checksum; + checksum = checksums::crc32(m_skipData.get(), priv::SKIP_CHECKSUM_OFFSET); + utility::BigUint32(checksum); + *(atUint32*)(m_skipData.get() + priv::SKIP_CHECKSUM_OFFSET) = checksum; } -void SkywardSwordQuest::setNew(bool isNew) -{ - *(bool*)(m_data.get() + priv::ISNEW_OFFSET) = isNew; -} +void SkywardSwordQuest::setNew(bool isNew) { *(bool*)(m_data.get() + priv::ISNEW_OFFSET) = isNew; } -bool SkywardSwordQuest::isNew() const -{ - return *(bool*)(m_data.get() + priv::ISNEW_OFFSET); -} +bool SkywardSwordQuest::isNew() const { return *(bool*)(m_data.get() + priv::ISNEW_OFFSET); } -} // zelda +} // namespace athena diff --git a/src/athena/Socket.cpp b/src/athena/Socket.cpp index 0b283b8..4add125 100644 --- a/src/athena/Socket.cpp +++ b/src/athena/Socket.cpp @@ -13,8 +13,7 @@ #include #endif -namespace athena::net -{ +namespace athena::net { /* Define the low-level send/receive flags, which depend on the OS */ #ifdef __linux__ @@ -23,282 +22,248 @@ static const int _flags = MSG_NOSIGNAL; static const int _flags = 0; #endif -void IPAddress::resolve(const std::string& address) -{ - m_address = 0; - m_valid = false; +void IPAddress::resolve(const std::string& address) { + m_address = 0; + m_valid = false; - if (address == "255.255.255.255") - { - /* The broadcast address needs to be handled explicitly, - * because it is also the value returned by inet_addr on error */ - m_address = INADDR_BROADCAST; - m_valid = true; - } - else if (address == "0.0.0.0") - { - m_address = INADDR_ANY; - m_valid = true; - } - else - { - /* Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") */ - struct in_addr addr; - if (inet_pton(AF_INET, address.c_str(), &addr) == 1) - { - m_address = addr.s_addr; - m_valid = true; - } - else - { - /* Not a valid address, try to convert it as a host name */ - addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - addrinfo* result = NULL; - if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0) - { - if (result) - { - addr = reinterpret_cast(result->ai_addr)->sin_addr; - freeaddrinfo(result); - m_address = addr.s_addr; - m_valid = true; - } - } + if (address == "255.255.255.255") { + /* The broadcast address needs to be handled explicitly, + * because it is also the value returned by inet_addr on error */ + m_address = INADDR_BROADCAST; + m_valid = true; + } else if (address == "0.0.0.0") { + m_address = INADDR_ANY; + m_valid = true; + } else { + /* Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") */ + struct in_addr addr; + if (inet_pton(AF_INET, address.c_str(), &addr) == 1) { + m_address = addr.s_addr; + m_valid = true; + } else { + /* Not a valid address, try to convert it as a host name */ + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + addrinfo* result = NULL; + if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0) { + if (result) { + addr = reinterpret_cast(result->ai_addr)->sin_addr; + freeaddrinfo(result); + m_address = addr.s_addr; + m_valid = true; } + } } + } } -uint32_t IPAddress::toInteger() const -{ - return ntohl(m_address); -} +uint32_t IPAddress::toInteger() const { return ntohl(m_address); } -static sockaddr_in createAddress(uint32_t address, unsigned short port) -{ - sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(address); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); +static sockaddr_in createAddress(uint32_t address, unsigned short port) { + sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(address); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); #ifdef __APPLE__ - addr.sin_len = sizeof(addr); + addr.sin_len = sizeof(addr); #endif - return addr; + return addr; } -bool Socket::openSocket() -{ - if (isOpen()) - return false; +bool Socket::openSocket() { + if (isOpen()) + return false; - m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (m_socket == -1) - { - atError("Can't allocate socket"); - return false; - } + m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (m_socket == -1) { + atError("Can't allocate socket"); + return false; + } - int one = 1; - setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&one), sizeof(one)); + int one = 1; + setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&one), sizeof(one)); #ifdef __APPLE__ - setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast(&one), sizeof(one)); + setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast(&one), sizeof(one)); #endif - setBlocking(m_isBlocking); + setBlocking(m_isBlocking); - return true; + return true; } -void Socket::setRemoteSocket(int remSocket) -{ - close(); - m_socket = remSocket; - setBlocking(m_isBlocking); +void Socket::setRemoteSocket(int remSocket) { + close(); + m_socket = remSocket; + setBlocking(m_isBlocking); } #ifdef _WIN32 -Socket::EResult Socket::LastWSAError() -{ - switch (WSAGetLastError()) - { - case WSAEWOULDBLOCK: - case WSAEALREADY: - return EResult::Busy; - default: - return EResult::Error; - } +Socket::EResult Socket::LastWSAError() { + switch (WSAGetLastError()) { + case WSAEWOULDBLOCK: + case WSAEALREADY: + return EResult::Busy; + default: + return EResult::Error; + } } #endif -void Socket::setBlocking(bool blocking) -{ - m_isBlocking = blocking; +void Socket::setBlocking(bool blocking) { + m_isBlocking = blocking; #ifndef _WIN32 - int status = fcntl(m_socket, F_GETFL); - if (m_isBlocking) - fcntl(m_socket, F_SETFL, status & ~O_NONBLOCK); - else - fcntl(m_socket, F_SETFL, status | O_NONBLOCK); + int status = fcntl(m_socket, F_GETFL); + if (m_isBlocking) + fcntl(m_socket, F_SETFL, status & ~O_NONBLOCK); + else + fcntl(m_socket, F_SETFL, status | O_NONBLOCK); #else - u_long b = blocking ? 0 : 1; - ioctlsocket(m_socket, FIONBIO, &b); + u_long b = blocking ? 0 : 1; + ioctlsocket(m_socket, FIONBIO, &b); #endif } -bool Socket::openAndListen(const IPAddress& address, uint32_t port) -{ - if (!openSocket()) - return false; +bool Socket::openAndListen(const IPAddress& address, uint32_t port) { + if (!openSocket()) + return false; - sockaddr_in addr = createAddress(address.toInteger(), port); - if (bind(m_socket, reinterpret_cast(&addr), sizeof(addr)) == -1) - { - /* Not likely to happen, but... */ - atError("Failed to bind listener socket to port %d", port); - return false; - } + sockaddr_in addr = createAddress(address.toInteger(), port); + if (bind(m_socket, reinterpret_cast(&addr), sizeof(addr)) == -1) { + /* Not likely to happen, but... */ + atError("Failed to bind listener socket to port %d", port); + return false; + } - if (::listen(m_socket, 0) == -1) - { - /* Oops, socket is deaf */ - atError("Failed to listen to port %d", port); - return false; - } + if (::listen(m_socket, 0) == -1) { + /* Oops, socket is deaf */ + atError("Failed to listen to port %d", port); + return false; + } - return true; + return true; } -Socket::EResult Socket::accept(Socket& remoteSocketOut, sockaddr_in& fromAddress) -{ - if (!isOpen()) - return EResult::Error; +Socket::EResult Socket::accept(Socket& remoteSocketOut, sockaddr_in& fromAddress) { + if (!isOpen()) + return EResult::Error; - /* Accept a new connection */ - socklen_t length = sizeof(sockaddr_in); - int remoteSocket = ::accept(m_socket, reinterpret_cast(&fromAddress), &length); + /* Accept a new connection */ + socklen_t length = sizeof(sockaddr_in); + int remoteSocket = ::accept(m_socket, reinterpret_cast(&fromAddress), &length); + + /* Check for errors */ + if (remoteSocket == -1) { +#ifndef _WIN32 + EResult res = (errno == EAGAIN) ? EResult::Busy : EResult::Error; + if (res == EResult::Error) + atError("Failed to accept incoming connection: %s", strerror(errno)); +#else + EResult res = LastWSAError(); + if (res == EResult::Error) + atError("Failed to accept incoming connection"); +#endif + return res; + } + + /* Initialize the new connected socket */ + remoteSocketOut.setRemoteSocket(remoteSocket); + + return EResult::OK; +} + +Socket::EResult Socket::accept(Socket& remoteSocketOut) { + sockaddr_in fromAddress; + return accept(remoteSocketOut, fromAddress); +} + +Socket::EResult Socket::accept(Socket& remoteSocketOut, std::string& fromHostname) { + sockaddr_in fromAddress; + socklen_t len = sizeof(fromAddress); + char name[NI_MAXHOST]; + EResult res = accept(remoteSocketOut, fromAddress); + if (res == EResult::OK) + if (getnameinfo((sockaddr*)&fromAddress, len, name, NI_MAXHOST, nullptr, 0, 0) == 0) + fromHostname.assign(name); + return res; +} + +void Socket::close() { + if (!isOpen()) + return; +#ifndef _WIN32 + ::close(m_socket); +#else + closesocket(m_socket); +#endif + m_socket = -1; +} + +Socket::EResult Socket::send(const void* buf, size_t len, size_t& transferred) { + transferred = 0; + if (!isOpen()) + return EResult::Error; + + if (!buf || !len) + return EResult::Error; + + /* Loop until every byte has been sent */ + int result = 0; + for (size_t sent = 0; sent < len; sent += result) { + /* Send a chunk of data */ + result = ::send(m_socket, static_cast(buf) + sent, len - sent, _flags); /* Check for errors */ - if (remoteSocket == -1) - { -#ifndef _WIN32 - EResult res = (errno == EAGAIN) ? EResult::Busy : EResult::Error; - if (res == EResult::Error) - atError("Failed to accept incoming connection: %s", strerror(errno)); -#else - EResult res = LastWSAError(); - if (res == EResult::Error) - atError("Failed to accept incoming connection"); -#endif - return res; - } - - /* Initialize the new connected socket */ - remoteSocketOut.setRemoteSocket(remoteSocket); - - return EResult::OK; -} - -Socket::EResult Socket::accept(Socket& remoteSocketOut) -{ - sockaddr_in fromAddress; - return accept(remoteSocketOut, fromAddress); -} - -Socket::EResult Socket::accept(Socket& remoteSocketOut, std::string& fromHostname) -{ - sockaddr_in fromAddress; - socklen_t len = sizeof(fromAddress); - char name[NI_MAXHOST]; - EResult res = accept(remoteSocketOut, fromAddress); - if (res == EResult::OK) - if (getnameinfo((sockaddr*)&fromAddress, len, name, NI_MAXHOST, nullptr, 0, 0) == 0) - fromHostname.assign(name); - return res; -} - -void Socket::close() -{ - if (!isOpen()) - return; -#ifndef _WIN32 - ::close(m_socket); -#else - closesocket(m_socket); -#endif - m_socket = -1; -} - -Socket::EResult Socket::send(const void* buf, size_t len, size_t& transferred) -{ - transferred = 0; - if (!isOpen()) - return EResult::Error; - - if (!buf || !len) - return EResult::Error; - - /* Loop until every byte has been sent */ - int result = 0; - for (size_t sent = 0; sent < len; sent += result) - { - /* Send a chunk of data */ - result = ::send(m_socket, static_cast(buf) + sent, len - sent, _flags); - - /* Check for errors */ - if (result < 0) -#ifndef _WIN32 - return (errno == EAGAIN) ? EResult::Busy : EResult::Error; -#else - return LastWSAError(); -#endif - } - - transferred = len; - return EResult::OK; -} - -Socket::EResult Socket::send(const void* buf, size_t len) -{ - size_t transferred; - return send(buf, len, transferred); -} - -Socket::EResult Socket::recv(void* buf, size_t len, size_t& transferred) -{ - transferred = 0; - if (!isOpen()) - return EResult::Error; - - if (!buf) - return EResult::Error; - - if (!len) - return EResult::OK; - - /* Receive a chunk of bytes */ - int result = ::recv(m_socket, static_cast(buf), static_cast(len), _flags); - if (result < 0) #ifndef _WIN32 - return (errno == EAGAIN) ? EResult::Busy : EResult::Error; + return (errno == EAGAIN) ? EResult::Busy : EResult::Error; #else - return LastWSAError(); + return LastWSAError(); #endif - else if (result == 0) - return EResult::Error; + } - transferred = result; + transferred = len; + return EResult::OK; +} + +Socket::EResult Socket::send(const void* buf, size_t len) { + size_t transferred; + return send(buf, len, transferred); +} + +Socket::EResult Socket::recv(void* buf, size_t len, size_t& transferred) { + transferred = 0; + if (!isOpen()) + return EResult::Error; + + if (!buf) + return EResult::Error; + + if (!len) return EResult::OK; + + /* Receive a chunk of bytes */ + int result = ::recv(m_socket, static_cast(buf), static_cast(len), _flags); + + if (result < 0) +#ifndef _WIN32 + return (errno == EAGAIN) ? EResult::Busy : EResult::Error; +#else + return LastWSAError(); +#endif + else if (result == 0) + return EResult::Error; + + transferred = result; + return EResult::OK; } -Socket::EResult Socket::recv(void* buf, size_t len) -{ - size_t transferred; - return recv(buf, len, transferred); +Socket::EResult Socket::recv(void* buf, size_t len) { + size_t transferred; + return recv(buf, len, transferred); } -} +} // namespace athena::net diff --git a/src/athena/Sprite.cpp b/src/athena/Sprite.cpp index 370f38c..d9b83b7 100644 --- a/src/athena/Sprite.cpp +++ b/src/athena/Sprite.cpp @@ -7,226 +7,152 @@ #include #endif -namespace athena::Sakura -{ -Sprite::Sprite(SpriteFile* root) - : m_root(root), - m_currentState(0), - m_currentFrame(0) -{ +namespace athena::Sakura { +Sprite::Sprite(SpriteFile* root) : m_root(root), m_currentState(0), m_currentFrame(0) {} + +Sprite::Sprite(SpriteFile* root, const std::string& name) : m_root(root), m_currentState(0) { m_name = name; } + +Sprite::~Sprite() { + for (SpriteFrame* frame : m_frames) { + delete frame; + frame = NULL; + } + + m_frames.clear(); } -Sprite::Sprite(SpriteFile* root, const std::string& name) - : m_root(root), - m_currentState(0) -{ - m_name = name; +void Sprite::setPosition(const float x, const float y) { setPosition(Vector2Df(x, y)); } + +void Sprite::setPosition(const Vector2Df& pos) { m_position = pos; } + +Vector2Df Sprite::position() const { return m_position; } + +void Sprite::setName(const std::string& name) { m_name = name; } + +std::string Sprite::name() const { return m_name; } + +void Sprite::addStateId(int id) { + if (m_stateIds.size() >= 65536) + return; + + if (std::find(m_stateIds.begin(), m_stateIds.end(), id) == m_stateIds.end()) + m_stateIds.push_back(id); } -Sprite::~Sprite() -{ - for (SpriteFrame* frame : m_frames) - { - delete frame; - frame = NULL; +int Sprite::stateId(int index) const { + if (index >= (int)m_stateIds.size()) + return -1; + + return m_stateIds[index]; +} + +void Sprite::setStateIds(std::vector ids) { + if (ids.size() == 0) + return; + + m_stateIds = ids; +} + +std::vector Sprite::stateIds() const { return m_stateIds; } + +atUint32 Sprite::stateCount() const { return (atUint32)m_stateIds.size(); } + +void Sprite::setCurrentState(const atUint32 id) { + if (id >= m_stateIds.size()) + return; + + m_currentState = id; +} + +atUint32 Sprite::currentState() const { return m_currentState; } + +bool Sprite::addFrame(SpriteFrame* part) { + if (m_frames.size() > 65536) + return false; + + for (SpriteFrame* tmp : m_frames) { + if (tmp == part) + return false; + } + + m_frames.push_back(part); + return true; +} + +bool Sprite::removeFrame(SpriteFrame* frame) { + std::vector::iterator iter = std::find(m_frames.begin(), m_frames.end(), frame); + + if (iter != m_frames.end()) { + m_frames.erase(iter); + return true; + } + return false; +} + +void Sprite::setFrame(atUint32 id) { + if (id > m_frames.size()) + return; +} + +void Sprite::setFrames(std::vector frames) { + if (frames.size() == 0) + return; + + if (m_frames.size() > 0) { + for (SpriteFrame* frame : m_frames) { + delete frame; + frame = NULL; } m_frames.clear(); + } + + m_frames = frames; } -void Sprite::setPosition(const float x, const float y) -{ - setPosition(Vector2Df(x, y)); -} +atUint32 Sprite::frameCount() const { return (atUint32)m_frames.size(); } -void Sprite::setPosition(const Vector2Df& pos) -{ - m_position = pos; -} +std::vector Sprite::frames() const { return m_frames; } -Vector2Df Sprite::position() const -{ - return m_position; -} +SpriteFile* Sprite::container() const { return m_root; } -void Sprite::setName(const std::string& name) -{ - m_name = name; -} +void Sprite::setCurrentFrame(SpriteFrame* frame) { + atUint32 id = 0; -std::string Sprite::name() const -{ - return m_name; -} - -void Sprite::addStateId(int id) -{ - if (m_stateIds.size() >= 65536) - return; - - if (std::find(m_stateIds.begin(), m_stateIds.end(), id) == m_stateIds.end()) - m_stateIds.push_back(id); -} - -int Sprite::stateId(int index) const -{ - if (index >= (int)m_stateIds.size()) - return -1; - - return m_stateIds[index]; -} - -void Sprite::setStateIds(std::vector ids) -{ - if (ids.size() == 0) - return; - - m_stateIds = ids; -} - -std::vector Sprite::stateIds() const -{ - return m_stateIds; -} - -atUint32 Sprite::stateCount() const -{ - return (atUint32)m_stateIds.size(); -} - -void Sprite::setCurrentState(const atUint32 id) -{ - if (id >= m_stateIds.size()) - return; - - m_currentState = id; -} - -atUint32 Sprite::currentState() const -{ - return m_currentState; -} - -bool Sprite::addFrame(SpriteFrame* part) -{ - if (m_frames.size() > 65536) - return false; - - for (SpriteFrame* tmp : m_frames) - { - if (tmp == part) - return false; + for (SpriteFrame* tmpFrame : m_frames) { + if (tmpFrame == frame) { + setCurrentFrame(id); + return; } - m_frames.push_back(part); - return true; + id++; + } } -bool Sprite::removeFrame(SpriteFrame* frame) -{ - std::vector::iterator iter = std::find(m_frames.begin(), m_frames.end(), frame); +void Sprite::setCurrentFrame(atUint32 id) { + if (id >= m_frames.size()) + return; - if (iter != m_frames.end()) - { - m_frames.erase(iter); - return true; - } - return false; + m_currentFrame = id; } -void Sprite::setFrame(atUint32 id) -{ - if (id > m_frames.size()) - return; +SpriteFrame* Sprite::currentFrame() const { return m_frames[m_currentFrame]; } + +void Sprite::advanceFrame() { + m_currentFrame++; + + if (m_currentFrame >= m_frames.size()) + m_currentFrame = (atUint32)m_frames.size() - 1; } -void Sprite::setFrames(std::vector frames) -{ - if (frames.size() == 0) - return; +void Sprite::retreatFrame() { + if (m_currentFrame == 0) + return; - if (m_frames.size() > 0) - { - for (SpriteFrame* frame : m_frames) - { - delete frame; - frame = NULL; - } - - m_frames.clear(); - } - - m_frames = frames; + m_currentFrame--; } +void Sprite::setRoot(SpriteFile* root) { m_root = root; } -atUint32 Sprite::frameCount() const -{ - return (atUint32)m_frames.size(); -} - -std::vector Sprite::frames() const -{ - return m_frames; -} - -SpriteFile* Sprite::container() const -{ - return m_root; -} - -void Sprite::setCurrentFrame(SpriteFrame* frame) -{ - atUint32 id = 0; - - for (SpriteFrame* tmpFrame : m_frames) - { - if (tmpFrame == frame) - { - setCurrentFrame(id); - return; - } - - id++; - } -} - -void Sprite::setCurrentFrame(atUint32 id) -{ - if (id >= m_frames.size()) - return; - - m_currentFrame = id; -} - -SpriteFrame* Sprite::currentFrame() const -{ - return m_frames[m_currentFrame]; -} - -void Sprite::advanceFrame() -{ - m_currentFrame++; - - if (m_currentFrame >= m_frames.size()) - m_currentFrame = (atUint32)m_frames.size() - 1; -} - -void Sprite::retreatFrame() -{ - if (m_currentFrame == 0) - return; - - m_currentFrame--; -} - -void Sprite::setRoot(SpriteFile* root) -{ - m_root = root; -} - -SpriteFile* Sprite::root() const -{ - return m_root; -} -} +SpriteFile* Sprite::root() const { return m_root; } +} // namespace athena::Sakura diff --git a/src/athena/SpriteFile.cpp b/src/athena/SpriteFile.cpp index 31f54fb..6381b41 100644 --- a/src/athena/SpriteFile.cpp +++ b/src/athena/SpriteFile.cpp @@ -3,8 +3,7 @@ #include "athena/Utility.hpp" #include -namespace athena::Sakura -{ +namespace athena::Sakura { const atUint32 SpriteFile::Major = 1; const atUint32 SpriteFile::Minor = 0; const atUint32 SpriteFile::Revision = 2; @@ -13,205 +12,135 @@ const atUint32 SpriteFile::Version = Major | (Minor << 8) | (Revision << 16) | ( const atUint32 SpriteFile::Magic = 'S' | ('P' << 8) | ('R' << 16) | ('S' << 24); - -SpriteFile::SpriteFile() -{ -} +SpriteFile::SpriteFile() {} SpriteFile::SpriteFile(atUint32 width, atUint32 height, float originX, float originY) - : m_size(width, height), - m_origin(originX, originY) -{ +: m_size(width, height), m_origin(originX, originY) {} + +SpriteFile::SpriteFile(const Vector2Di& size, const Vector2Df& origin) : m_size(size), m_origin(origin) {} + +SpriteFile::~SpriteFile() { + for (std::pair sprite : m_sprites) { + delete sprite.second; + sprite.second = NULL; + } + + m_sprites.clear(); } -SpriteFile::SpriteFile(const Vector2Di& size, const Vector2Df& origin) - : m_size(size), - m_origin(origin) -{ +void SpriteFile::setSize(atUint32 width, atUint32 height) { setSize(Vector2Di(width, height)); } + +void SpriteFile::setSize(const Vector2Di& size) { m_size = size; } + +Vector2Di SpriteFile::size() const { return m_size; } + +atUint32 SpriteFile::width() const { return m_size.x; } + +atUint32 SpriteFile::height() const { return m_size.y; } + +void SpriteFile::setOrigin(const float x, const float y) { setOrigin(Vector2Df(x, y)); } + +void SpriteFile::setOrigin(const Vector2Df& origin) { m_origin = origin; } + +Vector2Df SpriteFile::origin() const { return m_origin; } + +float SpriteFile::originX() const { return m_origin.x; } + +float SpriteFile::originY() const { return m_origin.y; } + +bool SpriteFile::addTexture(STexture* texture) { + if (m_textures.size() >= 65536) + return false; + + m_textures.push_back(texture); + return true; } -SpriteFile::~SpriteFile() -{ - for (std::pair sprite : m_sprites) - { - delete sprite.second; - sprite.second = NULL; +void SpriteFile::removeTexture(int id) { + if (id > (int)m_textures.size() || id < 0) + return; + + STexture* tex = m_textures[id]; + m_textures.erase(m_textures.begin() + id); + delete tex; +} + +STexture* SpriteFile::texture(atUint32 id) { + if (id >= m_textures.size()) + return NULL; + + return m_textures[id]; +} + +std::vector SpriteFile::textures() const { return m_textures; } + +atUint32 SpriteFile::textureCount() const { return (atUint32)m_textures.size(); } + +void SpriteFile::addSprite(Sprite* sprite) { + std::string name(sprite->name()); + athena::utility::tolower(name); + + if (m_sprites.find(name) != m_sprites.end()) + return; + + m_sprites[name] = sprite; +} + +void SpriteFile::removeSprite(const std::string& name) { + std::string tmpName(name); + athena::utility::tolower(tmpName); + std::unordered_map::iterator iterator = m_sprites.find(tmpName); + + if (iterator != m_sprites.end()) + m_sprites.erase(iterator); +} + +void SpriteFile::removeSprite(Sprite* sprite) { removeSprite(sprite->name()); } + +void SpriteFile::setSprites(std::unordered_map sprites) { + if (sprites.size() == 0) + return; + + if (m_sprites.size() > 0) { + for (std::pair sprite : m_sprites) { + delete sprite.second; + sprite.second = NULL; } m_sprites.clear(); + } + + m_sprites = sprites; } -void SpriteFile::setSize(atUint32 width, atUint32 height) -{ - setSize(Vector2Di(width, height)); +Sprite* SpriteFile::sprite(const std::string& name) { + std::string nameLow(name); + athena::utility::tolower(nameLow); + + if (m_sprites.find(nameLow) == m_sprites.end()) + return NULL; + + return m_sprites[nameLow]; } -void SpriteFile::setSize(const Vector2Di& size) -{ - m_size = size; -} +std::unordered_map SpriteFile::sprites() const { return m_sprites; } -Vector2Di SpriteFile::size() const -{ - return m_size; -} +atUint32 SpriteFile::spriteCount() const { return (atUint32)m_sprites.size(); } -atUint32 SpriteFile::width() const -{ - return m_size.x; -} +void SpriteFile::setTextures(std::vector textures) { + if (textures.size() == 0) + return; -atUint32 SpriteFile::height() const -{ - return m_size.y; -} - -void SpriteFile::setOrigin(const float x, const float y) -{ - setOrigin(Vector2Df(x, y)); -} - -void SpriteFile::setOrigin(const Vector2Df& origin) -{ - m_origin = origin; -} - - -Vector2Df SpriteFile::origin() const -{ - return m_origin; -} - -float SpriteFile::originX() const -{ - return m_origin.x; -} - -float SpriteFile::originY() const -{ - return m_origin.y; -} - -bool SpriteFile::addTexture(STexture* texture) -{ - if (m_textures.size() >= 65536) - return false; - - m_textures.push_back(texture); - return true; -} - -void SpriteFile::removeTexture(int id) -{ - if (id > (int)m_textures.size() || id < 0) - return; - - STexture* tex = m_textures[id]; - m_textures.erase(m_textures.begin() + id); - delete tex; -} - -STexture* SpriteFile::texture(atUint32 id) -{ - if (id >= m_textures.size()) - return NULL; - - return m_textures[id]; -} - -std::vector SpriteFile::textures() const -{ - return m_textures; -} - -atUint32 SpriteFile::textureCount() const -{ - return (atUint32)m_textures.size(); -} - -void SpriteFile::addSprite(Sprite* sprite) -{ - std::string name(sprite->name()); - athena::utility::tolower(name); - - if (m_sprites.find(name) != m_sprites.end()) - return; - - m_sprites[name] = sprite; -} - -void SpriteFile::removeSprite(const std::string& name) -{ - std::string tmpName(name); - athena::utility::tolower(tmpName); - std::unordered_map::iterator iterator = m_sprites.find(tmpName); - - if (iterator != m_sprites.end()) - m_sprites.erase(iterator); -} - -void SpriteFile::removeSprite(Sprite* sprite) -{ - removeSprite(sprite->name()); -} - -void SpriteFile::setSprites(std::unordered_map sprites) -{ - if (sprites.size() == 0) - return; - - if (m_sprites.size() > 0) - { - for (std::pair sprite : m_sprites) - { - delete sprite.second; - sprite.second = NULL; - } - - m_sprites.clear(); + if (m_textures.size() > 0) { + for (STexture* tex : m_textures) { + delete tex; + tex = NULL; } - m_sprites = sprites; + m_textures.clear(); + } + + m_textures = textures; } -Sprite* SpriteFile::sprite(const std::string& name) -{ - std::string nameLow(name); - athena::utility::tolower(nameLow); - - if (m_sprites.find(nameLow) == m_sprites.end()) - return NULL; - - return m_sprites[nameLow]; -} - -std::unordered_map SpriteFile::sprites() const -{ - return m_sprites; -} - -atUint32 SpriteFile::spriteCount() const -{ - return (atUint32)m_sprites.size(); -} - -void SpriteFile::setTextures(std::vector textures) -{ - if (textures.size() == 0) - return; - - if (m_textures.size() > 0) - { - for (STexture* tex : m_textures) - { - delete tex; - tex = NULL; - } - - m_textures.clear(); - } - - m_textures = textures; -} - -} // zelda +} // namespace athena::Sakura diff --git a/src/athena/SpriteFileReader.cpp b/src/athena/SpriteFileReader.cpp index db1982c..5a3711a 100644 --- a/src/athena/SpriteFileReader.cpp +++ b/src/athena/SpriteFileReader.cpp @@ -5,201 +5,183 @@ #include "athena/SpriteFrame.hpp" #include "athena/Utility.hpp" -namespace athena::io -{ -SpriteFileReader::SpriteFileReader(atUint8* data, atUint64 length) - : MemoryCopyReader(data, length) -{ -} +namespace athena::io { +SpriteFileReader::SpriteFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {} -SpriteFileReader::SpriteFileReader(const std::string& filepath) - : MemoryCopyReader(filepath) -{ +SpriteFileReader::SpriteFileReader(const std::string& filepath) : MemoryCopyReader(filepath) {} -} +Sakura::SpriteFile* SpriteFileReader::readFile() { + Sakura::SpriteFile* ret = NULL; -Sakura::SpriteFile* SpriteFileReader::readFile() -{ - Sakura::SpriteFile* ret = NULL; + atUint32 magic = readUint32(); - atUint32 magic = readUint32(); + if (magic != Sakura::SpriteFile::Magic) { + atError("Not a valid Sakura Sprite container"); + return nullptr; + } - if (magic != Sakura::SpriteFile::Magic) - { - atError("Not a valid Sakura Sprite container"); - return nullptr; - } + atUint32 version = readUint32(); - atUint32 version = readUint32(); + // TODO: Make this more verbose + if (version != Sakura::SpriteFile::Version) { + atError("Unsupported version"); + return nullptr; + } - // TODO: Make this more verbose - if (version != Sakura::SpriteFile::Version) - { - atError("Unsupported version"); - return nullptr; - } + // After reading in the magic and version we need to load some + // metadata about the file. + // Such as the texture count, it's dimensions, and it's origin. + // After that we have the number of sprites contained in this + // sprite container. + atUint16 textureCount = + readUint16(); // Having it as a Uint16 gives us the ability to have up to 65536 different states + // This is probably overkill, but it's better safe than sorry. + atUint32 width = readUint32(); + atUint32 height = readUint32(); + float originX = readFloat(); + float originY = readFloat(); + atUint16 spriteCount = readUint16(); - // After reading in the magic and version we need to load some - // metadata about the file. - // Such as the texture count, it's dimensions, and it's origin. - // After that we have the number of sprites contained in this - // sprite container. - atUint16 textureCount = readUint16(); // Having it as a Uint16 gives us the ability to have up to 65536 different states - // This is probably overkill, but it's better safe than sorry. - atUint32 width = readUint32(); - atUint32 height = readUint32(); - float originX = readFloat(); - float originY = readFloat(); - atUint16 spriteCount = readUint16(); + // Lets go ahead and create or new container. + ret = new Sakura::SpriteFile(width, height, originX, originY); - // Lets go ahead and create or new container. - ret = new Sakura::SpriteFile(width, height, originX, originY); + // The next four bytes are reserved to keep the header 32 byte aligned. + // This isn't necessary for most systems, but it's eventually planned + // to migrate this code to Big Endian based systems, such as the wii + // which require data to be 32 byte aligned, or it causes some issues. + // It's also convenient to have this, for later expansion. + atUint32 reserved = readUint32(); + UNUSED(reserved); - // The next four bytes are reserved to keep the header 32 byte aligned. - // This isn't necessary for most systems, but it's eventually planned - // to migrate this code to Big Endian based systems, such as the wii - // which require data to be 32 byte aligned, or it causes some issues. - // It's also convenient to have this, for later expansion. - atUint32 reserved = readUint32(); - UNUSED(reserved); - - // Next we have to load the textures - // If we tried to add them one at a time to the sprite container - // it will be slow as hell, so we store them in a vector locally - // then give that vector the the container, this bypasses the de-reference - // for each texture + // Next we have to load the textures + // If we tried to add them one at a time to the sprite container + // it will be slow as hell, so we store them in a vector locally + // then give that vector the the container, this bypasses the de-reference + // for each texture #ifndef ATHENA_USE_QT - std::vector textures; + std::vector textures; #else - QList textures; + QList textures; #endif - for (atUint16 i = 0; i < textureCount; i++) - { - Sakura::STexture* texture = new Sakura::STexture; - texture->Filepath = readString(); - texture->Preload = readBool(); - textures.push_back(texture); - } + for (atUint16 i = 0; i < textureCount; i++) { + Sakura::STexture* texture = new Sakura::STexture; + texture->Filepath = readString(); + texture->Preload = readBool(); + textures.push_back(texture); + } - ret->setTextures(textures); + ret->setTextures(textures); - // Now for the sprites - // The sprites are a bit more difficult, they are stored in an unordered_map - // with it's name as the key, this means we can't have two sprites with the same name - // Normally this isn't a problem, but someone may decide to copy and paste a sprite - // and forget to change the name, that needs to be handled, but it's outside the scope - // of this reader. + // Now for the sprites + // The sprites are a bit more difficult, they are stored in an unordered_map + // with it's name as the key, this means we can't have two sprites with the same name + // Normally this isn't a problem, but someone may decide to copy and paste a sprite + // and forget to change the name, that needs to be handled, but it's outside the scope + // of this reader. #ifndef ATHENA_USE_QT - std::unordered_map sprites; + std::unordered_map sprites; #else - QMap sprites; + QMap sprites; #endif - for (atUint16 i = 0; i < spriteCount; i++) - { - Sakura::Sprite* sprite = new Sakura::Sprite(ret); + for (atUint16 i = 0; i < spriteCount; i++) { + Sakura::Sprite* sprite = new Sakura::Sprite(ret); +#ifndef ATHENA_USE_QT + std::string name = readString(); +#else + QString name = QString::fromStdString(readString()); +#endif + sprite->setName(name); + atUint16 frameCount = readUint16(); + atUint16 stateCount = readUint16(); + + // Each state id corresponds to a texture held in the parent class + std::vector stateIds; + + for (int j = 0; j < stateCount; j++) + stateIds.push_back(readUint16()); + + sprite->setStateIds(stateIds); + + // Now to read the sprite parts. + // The parts allow us to build retro style sprites very easily + // making it possible to use one texture atlas for all possible + // frame combinations, this reduces the amount of memory overhead + // and the storage footprint, while Sakura supports packs and zips + // it's still a bad idea to have a metric ton of texture resources + // littering the place +#ifndef ATHENA_USE_QT + std::vector frames; +#else + QList frames; +#endif + + for (atUint32 k = 0; k < frameCount; k++) { + Sakura::SpriteFrame* frame = new Sakura::SpriteFrame(sprite); + frame->setFrameTime(readFloat()); + atUint16 partCount = readUint16(); + +#ifndef ATHENA_USE_QT + std::vector parts; +#else + QList parts; +#endif + + for (atUint8 j = 0; j < partCount; j++) { + Sakura::SpritePart* part = new Sakura::SpritePart(frame); #ifndef ATHENA_USE_QT std::string name = readString(); #else QString name = QString::fromStdString(readString()); #endif - sprite->setName(name); - atUint16 frameCount = readUint16(); - atUint16 stateCount = readUint16(); + part->setName(name); + part->setCollision(readBool()); - // Each state id corresponds to a texture held in the parent class - std::vector stateIds; + float xOff = readFloat(); + float yOff = readFloat(); + part->setOffset(xOff, yOff); + float texXOff = readFloat(); + float texYOff = readFloat(); + part->setTextureOffset(texXOff, texYOff); + atUint32 width = readUint32(); + atUint32 height = readUint32(); + part->setSize(width, height); + bool flippedH = readBool(); + part->setFlippedHorizontally(flippedH); + bool flippedV = readBool(); + part->setFlippedVertically(flippedV); - for (int j = 0; j < stateCount; j++) - stateIds.push_back(readUint16()); + parts.push_back(part); + } - - sprite->setStateIds(stateIds); - - // Now to read the sprite parts. - // The parts allow us to build retro style sprites very easily - // making it possible to use one texture atlas for all possible - // frame combinations, this reduces the amount of memory overhead - // and the storage footprint, while Sakura supports packs and zips - // it's still a bad idea to have a metric ton of texture resources - // littering the place -#ifndef ATHENA_USE_QT - std::vector frames; -#else - QList frames; -#endif - - for (atUint32 k = 0; k < frameCount; k++) - { - Sakura::SpriteFrame* frame = new Sakura::SpriteFrame(sprite); - frame->setFrameTime(readFloat()); - atUint16 partCount = readUint16(); - - -#ifndef ATHENA_USE_QT - std::vector parts; -#else - QList parts; -#endif - - for (atUint8 j = 0; j < partCount; j++) - { - Sakura::SpritePart* part = new Sakura::SpritePart(frame); -#ifndef ATHENA_USE_QT - std::string name = readString(); -#else - QString name = QString::fromStdString(readString()); -#endif - part->setName(name); - part->setCollision(readBool()); - - float xOff = readFloat(); - float yOff = readFloat(); - part->setOffset(xOff, yOff); - float texXOff = readFloat(); - float texYOff = readFloat(); - part->setTextureOffset(texXOff, texYOff); - atUint32 width = readUint32(); - atUint32 height = readUint32(); - part->setSize(width, height); - bool flippedH = readBool(); - part->setFlippedHorizontally(flippedH); - bool flippedV = readBool(); - part->setFlippedVertically(flippedV); - - parts.push_back(part); - } - - frame->setParts(parts); - frames.push_back(frame); - } - - sprite->setFrames(frames); -#ifndef ATHENA_USE_QT - - if (sprite->name() != std::string()) - { - std::string nameLow(sprite->name()); - athena::utility::tolower(nameLow); - sprites[nameLow] = sprite; - } - -#else - - if (!sprite->name().isEmpty()) - sprites[sprite->name().toLower()] = sprite; - -#endif - else - { - atError("Sprite names cannot be empty"); - return nullptr; - } + frame->setParts(parts); + frames.push_back(frame); } - ret->setSprites(sprites); + sprite->setFrames(frames); +#ifndef ATHENA_USE_QT - return ret; + if (sprite->name() != std::string()) { + std::string nameLow(sprite->name()); + athena::utility::tolower(nameLow); + sprites[nameLow] = sprite; + } + +#else + + if (!sprite->name().isEmpty()) + sprites[sprite->name().toLower()] = sprite; + +#endif + else { + atError("Sprite names cannot be empty"); + return nullptr; + } + } + + ret->setSprites(sprites); + + return ret; } -} // zelda +} // namespace athena::io diff --git a/src/athena/SpriteFileWriter.cpp b/src/athena/SpriteFileWriter.cpp index d76dec7..72b6bd5 100644 --- a/src/athena/SpriteFileWriter.cpp +++ b/src/athena/SpriteFileWriter.cpp @@ -4,76 +4,63 @@ #include "athena/SpritePart.hpp" #include "athena/SpriteFrame.hpp" -namespace athena::io -{ -SpriteFileWriter::SpriteFileWriter(atUint8* data, atUint64 length) - : MemoryCopyWriter(data, length) -{ +namespace athena::io { +SpriteFileWriter::SpriteFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {} + +SpriteFileWriter::SpriteFileWriter(std::string_view filepath) : MemoryCopyWriter(filepath) {} + +void SpriteFileWriter::writeFile(Sakura::SpriteFile* file) { + if (!file) { + atError("file cannot be NULL"); + return; + } + + writeUint32(Sakura::SpriteFile::Magic); + writeUint32(Sakura::SpriteFile::Version); + + writeUint16(file->textureCount()); + writeUint32(file->width()); + writeUint32(file->height()); + writeFloat(file->originX()); + writeFloat(file->originY()); + writeUint16(file->spriteCount()); + + writeUint32(0xFFFFFFFF); + + for (Sakura::STexture* texture : file->textures()) { + writeString(texture->Filepath); + writeBool(texture->Preload); + } + + for (std::pair spritePair : file->sprites()) { + Sakura::Sprite* sprite = spritePair.second; + writeString(sprite->name()); + writeUint16(sprite->frameCount()); + writeUint16(sprite->stateCount()); + + for (int id : sprite->stateIds()) + writeUint16(id); + + for (Sakura::SpriteFrame* frame : sprite->frames()) { + writeFloat(frame->frameTime()); + writeUint16(frame->partCount()); + + for (Sakura::SpritePart* part : frame->parts()) { + writeString(part->name()); + writeBool(part->hasCollision()); + writeFloat(part->offset().x); + writeFloat(part->offset().y); + writeFloat(part->textureOffset().x); + writeFloat(part->textureOffset().y); + writeUint32(part->size().x); + writeUint32(part->size().y); + writeBool(part->flippedHorizontally()); + writeBool(part->flippedVertically()); + } + } + } + + save(); } -SpriteFileWriter::SpriteFileWriter(std::string_view filepath) - : MemoryCopyWriter(filepath) -{ -} - -void SpriteFileWriter::writeFile(Sakura::SpriteFile* file) -{ - if (!file) - { - atError("file cannot be NULL"); - return; - } - - writeUint32(Sakura::SpriteFile::Magic); - writeUint32(Sakura::SpriteFile::Version); - - writeUint16(file->textureCount()); - writeUint32(file->width()); - writeUint32(file->height()); - writeFloat(file->originX()); - writeFloat(file->originY()); - writeUint16(file->spriteCount()); - - writeUint32(0xFFFFFFFF); - - for (Sakura::STexture* texture : file->textures()) - { - writeString(texture->Filepath); - writeBool(texture->Preload); - } - - for (std::pair spritePair : file->sprites()) - { - Sakura::Sprite* sprite = spritePair.second; - writeString(sprite->name()); - writeUint16(sprite->frameCount()); - writeUint16(sprite->stateCount()); - - for (int id : sprite->stateIds()) - writeUint16(id); - - for (Sakura::SpriteFrame* frame : sprite->frames()) - { - writeFloat(frame->frameTime()); - writeUint16(frame->partCount()); - - for (Sakura::SpritePart* part : frame->parts()) - { - writeString(part->name()); - writeBool(part->hasCollision()); - writeFloat(part->offset().x); - writeFloat(part->offset().y); - writeFloat(part->textureOffset().x); - writeFloat(part->textureOffset().y); - writeUint32(part->size().x); - writeUint32(part->size().y); - writeBool(part->flippedHorizontally()); - writeBool(part->flippedVertically()); - } - } - } - - save(); -} - -} // zelda +} // namespace athena::io diff --git a/src/athena/SpriteFrame.cpp b/src/athena/SpriteFrame.cpp index 4cbef44..ba2bf68 100644 --- a/src/athena/SpriteFrame.cpp +++ b/src/athena/SpriteFrame.cpp @@ -2,52 +2,27 @@ #include "athena/SpritePart.hpp" #include "athena/Sprite.hpp" -namespace athena::Sakura -{ +namespace athena::Sakura { -SpriteFrame::SpriteFrame() -{ +SpriteFrame::SpriteFrame() {} + +SpriteFrame::SpriteFrame(Sprite* root) : m_root(root) {} + +void SpriteFrame::setFrameTime(float frameTime) { m_frameTime = frameTime; } + +void SpriteFrame::setParts(std::vector parts) { m_parts = parts; } + +std::vector SpriteFrame::parts() const { return m_parts; } + +atUint32 SpriteFrame::partCount() const { return (atUint32)m_parts.size(); } + +float SpriteFrame::frameTime() const { return m_frameTime; } + +void SpriteFrame::setRoot(Sprite* root) { + root->removeFrame(this); + m_root = root; } -SpriteFrame::SpriteFrame(Sprite* root) - : m_root(root) -{ -} +Sprite* SpriteFrame::root() const { return m_root; } -void SpriteFrame::setFrameTime(float frameTime) -{ - m_frameTime = frameTime; -} - -void SpriteFrame::setParts(std::vector parts) -{ - m_parts = parts; -} - -std::vector SpriteFrame::parts() const -{ - return m_parts; -} - -atUint32 SpriteFrame::partCount() const -{ - return (atUint32)m_parts.size(); -} - -float SpriteFrame::frameTime() const -{ - return m_frameTime; -} - -void SpriteFrame::setRoot(Sprite* root) -{ - root->removeFrame(this); - m_root = root; -} - -Sprite* SpriteFrame::root() const -{ - return m_root; -} - -} // zelda +} // namespace athena::Sakura diff --git a/src/athena/SpritePart.cpp b/src/athena/SpritePart.cpp index a514918..192fee0 100644 --- a/src/athena/SpritePart.cpp +++ b/src/athena/SpritePart.cpp @@ -3,113 +3,50 @@ #include "athena/Sprite.hpp" #include -namespace athena::Sakura -{ +namespace athena::Sakura { -SpritePart::SpritePart(SpriteFrame* root) - : m_root(root), - m_hasCollision(false) -{ -} +SpritePart::SpritePart(SpriteFrame* root) : m_root(root), m_hasCollision(false) {} SpritePart::SpritePart(SpriteFrame* root, const std::string& name, bool hasCollision) - : m_root(root), - m_hasCollision(hasCollision) -{ - m_name = name; +: m_root(root), m_hasCollision(hasCollision) { + m_name = name; } -SpritePart::~SpritePart() -{ -} +SpritePart::~SpritePart() {} -void SpritePart::setName(const std::string& name) -{ - m_name = name; -} +void SpritePart::setName(const std::string& name) { m_name = name; } -std::string SpritePart::name() const -{ - return m_name; -} +std::string SpritePart::name() const { return m_name; } -void SpritePart::setCollision(bool col) -{ - m_hasCollision = col; -} +void SpritePart::setCollision(bool col) { m_hasCollision = col; } -bool SpritePart::hasCollision() const -{ - return m_hasCollision; -} +bool SpritePart::hasCollision() const { return m_hasCollision; } -void SpritePart::setOffset(float x, float y) -{ - setOffset(Vector2Df(x, y)); -} +void SpritePart::setOffset(float x, float y) { setOffset(Vector2Df(x, y)); } -void SpritePart::setOffset(const Vector2Df& offset) -{ - m_offset = offset; -} +void SpritePart::setOffset(const Vector2Df& offset) { m_offset = offset; } -Vector2Df SpritePart::offset() const -{ - return m_offset; -} +Vector2Df SpritePart::offset() const { return m_offset; } -void SpritePart::setTextureOffset(float x, float y) -{ - setTextureOffset(Vector2Df(x, y)); -} +void SpritePart::setTextureOffset(float x, float y) { setTextureOffset(Vector2Df(x, y)); } -void SpritePart::setTextureOffset(const Vector2Df& offset) -{ - m_textureOffset = offset; -} +void SpritePart::setTextureOffset(const Vector2Df& offset) { m_textureOffset = offset; } -Vector2Df SpritePart::textureOffset() const -{ - return m_textureOffset; -} +Vector2Df SpritePart::textureOffset() const { return m_textureOffset; } -void SpritePart::setSize(atUint32 width, atUint32 height) -{ - setSize(Vector2Di(width, height)); -} +void SpritePart::setSize(atUint32 width, atUint32 height) { setSize(Vector2Di(width, height)); } -void SpritePart::setSize(const Vector2Di& size) -{ - m_size = size; -} +void SpritePart::setSize(const Vector2Di& size) { m_size = size; } -Vector2Di SpritePart::size() const -{ - return m_size; -} +Vector2Di SpritePart::size() const { return m_size; } -void SpritePart::setFlippedHorizontally(const bool val) -{ - m_flippedH = val; -} +void SpritePart::setFlippedHorizontally(const bool val) { m_flippedH = val; } -bool SpritePart::flippedHorizontally() const -{ - return m_flippedH; -} +bool SpritePart::flippedHorizontally() const { return m_flippedH; } -void SpritePart::setFlippedVertically(const bool val) -{ - m_flippedV = val; -} +void SpritePart::setFlippedVertically(const bool val) { m_flippedV = val; } -bool SpritePart::flippedVertically() const -{ - return m_flippedV; -} +bool SpritePart::flippedVertically() const { return m_flippedV; } -SpriteFrame* SpritePart::root() const -{ - return m_root; -} -} +SpriteFrame* SpritePart::root() const { return m_root; } +} // namespace athena::Sakura diff --git a/src/athena/Utility.cpp b/src/athena/Utility.cpp index 6505f10..f51f8ea 100644 --- a/src/athena/Utility.cpp +++ b/src/athena/Utility.cpp @@ -17,240 +17,204 @@ #include #endif -namespace athena::utility -{ +namespace athena::utility { -void fillRandom(atUint8* rndArea, atUint64 count) -{ - atUint8* buf = rndArea; - for (atUint64 i = 0; i < count / 4; i++) - { - *(atUint32*)(buf) = rand(); - buf += 4; - } - - atUint64 rem = count % 4; - if (rem) - { - for (atUint64 j = 0; j < rem; j++) - { - *buf = rand(); - buf++; - } +void fillRandom(atUint8* rndArea, atUint64 count) { + atUint8* buf = rndArea; + for (atUint64 i = 0; i < count / 4; i++) { + *(atUint32*)(buf) = rand(); + buf += 4; + } + + atUint64 rem = count % 4; + if (rem) { + for (atUint64 j = 0; j < rem; j++) { + *buf = rand(); + buf++; } + } } -static std::vector& split(std::string_view s, char delim, std::vector& elems) -{ - std::string tmps(s); - std::stringstream ss(tmps); - std::string item; +static std::vector& split(std::string_view s, char delim, std::vector& elems) { + std::string tmps(s); + std::stringstream ss(tmps); + std::string item; - while (std::getline(ss, item, delim)) - elems.push_back(item); + while (std::getline(ss, item, delim)) + elems.push_back(item); - return elems; + return elems; } - -std::vector split(std::string_view s, char delim) -{ - std::vector elems; - split(s, delim, elems); - return elems; +std::vector split(std::string_view s, char delim) { + std::vector elems; + split(s, delim, elems); + return elems; } -std::string join(const std::vector& elems, std::string_view delims) -{ - std::ostringstream ret; - std::copy(elems.begin(), elems.end(), std::ostream_iterator(ret, delims.data())); +std::string join(const std::vector& elems, std::string_view delims) { + std::ostringstream ret; + std::copy(elems.begin(), elems.end(), std::ostream_iterator(ret, delims.data())); - return ret.str(); + return ret.str(); } -void tolower(std::string& str) -{ - std::transform(str.begin(), str.end(), str.begin(), ::tolower); -} +void tolower(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), ::tolower); } -void toupper(std::string& str) -{ - std::transform(str.begin(), str.end(), str.begin(), ::toupper); -} +void toupper(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), ::toupper); } -std::string vsprintf(const char* fmt, va_list list) -{ - int size = 512; - char* buffer = 0; - buffer = new char[size]; - int nsize = ::vsprintf(buffer, fmt, list); +std::string vsprintf(const char* fmt, va_list list) { + int size = 512; + char* buffer = 0; + buffer = new char[size]; + int nsize = ::vsprintf(buffer, fmt, list); - while (size <= nsize) - { - //fail delete buffer and try again - delete[] buffer; - buffer = 0; - buffer = new char[nsize + 1]; //+1 for /0 - nsize = ::vsprintf(buffer, fmt, list); - } - - std::string ret(buffer); + while (size <= nsize) { + // fail delete buffer and try again delete[] buffer; - return ret; + buffer = 0; + buffer = new char[nsize + 1]; //+1 for /0 + nsize = ::vsprintf(buffer, fmt, list); + } + + std::string ret(buffer); + delete[] buffer; + return ret; } -std::string sprintf(const char* fmt, ...) -{ - va_list vl; - va_start(vl, fmt); - std::string ret = vsprintf(fmt, vl); - va_end(vl); - return ret; +std::string sprintf(const char* fmt, ...) { + va_list vl; + va_start(vl, fmt); + std::string ret = vsprintf(fmt, vl); + va_end(vl); + return ret; } -bool parseBool(std::string_view boolean, bool* valid) -{ - std::string val(boolean); - // compare must be case insensitive - // This is the cleanest solution since I only need to do it once - tolower(val); - - // Check for true first - if (!val.compare("true") || !val.compare("1") || !val.compare("yes") || !val.compare("on")) - { - if (valid) - *valid = true; - - return true; - } - - // Now false - if (!val.compare("false") || !val.compare("0") || !val.compare("no") || !val.compare("off")) - { - if (valid) - *valid = true; - - return false; - } - - // Well that could've gone better +bool parseBool(std::string_view boolean, bool* valid) { + std::string val(boolean); + // compare must be case insensitive + // This is the cleanest solution since I only need to do it once + tolower(val); + // Check for true first + if (!val.compare("true") || !val.compare("1") || !val.compare("yes") || !val.compare("on")) { if (valid) - *valid = false; + *valid = true; + + return true; + } + + // Now false + if (!val.compare("false") || !val.compare("0") || !val.compare("no") || !val.compare("off")) { + if (valid) + *valid = true; return false; + } + + // Well that could've gone better + + if (valid) + *valid = false; + + return false; } -int countChar(std::string_view str, const char chr, int* lastOccur) -{ - int ret = 0; +int countChar(std::string_view str, const char chr, int* lastOccur) { + int ret = 0; - int index = 0; + int index = 0; - for (char c : str) - { - if (c == chr) - { - if (lastOccur != NULL) - *lastOccur = index; + for (char c : str) { + if (c == chr) { + if (lastOccur != NULL) + *lastOccur = index; - ret++; - } - - index++; + ret++; } - return ret; + index++; + } + + return ret; } -atUint64 fileSize(std::string_view filename) -{ - atStat64_t st; - atStat64(filename.data(), &st); - return st.st_size; +atUint64 fileSize(std::string_view filename) { + atStat64_t st; + atStat64(filename.data(), &st); + return st.st_size; } #ifdef _WIN32 -atUint64 fileSize(std::wstring_view filename) -{ - atStat64_t st; - _wstati64(filename.data(), &st); - return st.st_size; +atUint64 fileSize(std::wstring_view filename) { + atStat64_t st; + _wstati64(filename.data(), &st); + return st.st_size; } #endif // trim from both ends -std::string& trim(std::string& s) -{ - // Find first non whitespace char in StrToTrim - std::string::size_type first = s.find_first_not_of(' '); +std::string& trim(std::string& s) { + // Find first non whitespace char in StrToTrim + std::string::size_type first = s.find_first_not_of(' '); - // Check whether something went wrong? - if (first == std::string::npos) - { - first = 0; - } + // Check whether something went wrong? + if (first == std::string::npos) { + first = 0; + } - // Find last non whitespace char from StrToTrim - std::string::size_type last = s.find_last_not_of(' '); + // Find last non whitespace char from StrToTrim + std::string::size_type last = s.find_last_not_of(' '); - // If something didn't go wrong, Last will be recomputed to get real length of substring - if (last != std::string::npos) - { - last = (last + 1) - first; - } + // If something didn't go wrong, Last will be recomputed to get real length of substring + if (last != std::string::npos) { + last = (last + 1) - first; + } - // Copy such a string to TrimmedString - s = s.substr(first, last); + // Copy such a string to TrimmedString + s = s.substr(first, last); - return s; + return s; } -atUint64 rand64() -{ - // Combine 4 parts of low 16-bit of each rand() - atUint64 r0 = (atUint64)rand() << 48; - atUint64 r1 = (atUint64)rand() << 48 >> 16; - atUint64 r2 = (atUint64)rand() << 48 >> 32; - atUint64 r3 = (atUint64)rand() << 48 >> 48; - return r0 | r1 | r2 | r3; +atUint64 rand64() { + // Combine 4 parts of low 16-bit of each rand() + atUint64 r0 = (atUint64)rand() << 48; + atUint64 r1 = (atUint64)rand() << 48 >> 16; + atUint64 r2 = (atUint64)rand() << 48 >> 32; + atUint64 r3 = (atUint64)rand() << 48 >> 48; + return r0 | r1 | r2 | r3; } -std::string wideToUtf8(std::wstring_view src) -{ - std::string retval; - retval.reserve(src.length()); - for (wchar_t ch : src) - { - 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 retval; - } - retval.append(reinterpret_cast(mb), c); +std::string wideToUtf8(std::wstring_view src) { + std::string retval; + retval.reserve(src.length()); + for (wchar_t ch : src) { + 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 retval; } - return retval; + retval.append(reinterpret_cast(mb), c); + } + return retval; } -std::wstring utf8ToWide(std::string_view src) -{ - std::wstring retval; - retval.reserve(src.length()); - const utf8proc_uint8_t* buf = reinterpret_cast(src.data()); - 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 utf8ToWide(std::string_view src) { + std::wstring retval; + retval.reserve(src.length()); + const utf8proc_uint8_t* buf = reinterpret_cast(src.data()); + 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; } -} // Athena +} // namespace athena::utility diff --git a/src/athena/VectorWriter.cpp b/src/athena/VectorWriter.cpp index 6874610..7822e04 100644 --- a/src/athena/VectorWriter.cpp +++ b/src/athena/VectorWriter.cpp @@ -6,86 +6,75 @@ #include #include -namespace athena::io -{ +namespace athena::io { -void VectorWriter::seek(atInt64 position, SeekOrigin origin) -{ - switch (origin) - { - case SeekOrigin::Begin: - if (position < 0) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if ((atUint64)position > m_data.size()) - m_data.resize(position); - - m_position = position; - break; - - case SeekOrigin::Current: - if ((((atInt64)m_position + position) < 0)) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if (m_position + position > m_data.size()) - m_data.resize(m_position + position); - - m_position += position; - break; - - case SeekOrigin::End: - if (((atInt64)m_data.size() - position) < 0) - { - atError("Position outside stream bounds"); - setError(); - return; - } - - if ((atUint64)position > m_data.size()) - { - atError("data exceeds vector size"); - setError(); - return; - } - - m_position = m_data.size() - position; - break; +void VectorWriter::seek(atInt64 position, SeekOrigin origin) { + switch (origin) { + case SeekOrigin::Begin: + if (position < 0) { + atError("Position outside stream bounds"); + setError(); + return; } + + if ((atUint64)position > m_data.size()) + m_data.resize(position); + + m_position = position; + break; + + case SeekOrigin::Current: + if ((((atInt64)m_position + position) < 0)) { + atError("Position outside stream bounds"); + setError(); + return; + } + + if (m_position + position > m_data.size()) + m_data.resize(m_position + position); + + m_position += position; + break; + + case SeekOrigin::End: + if (((atInt64)m_data.size() - position) < 0) { + atError("Position outside stream bounds"); + setError(); + return; + } + + if ((atUint64)position > m_data.size()) { + atError("data exceeds vector size"); + setError(); + return; + } + + m_position = m_data.size() - position; + break; + } } -void VectorWriter::writeUBytes(const atUint8* data, atUint64 length) -{ - if (!data) - { - atError("data cannnot be NULL"); - setError(); - return; - } +void VectorWriter::writeUBytes(const atUint8* data, atUint64 length) { + if (!data) { + atError("data cannnot be NULL"); + setError(); + return; + } - if (m_position < m_data.size()) - { - size_t delta = std::min(m_data.size() - m_position, length); - memmove(reinterpret_cast(&m_data[m_position]), data, delta); - data += delta; - length -= delta; - m_position += delta; - } + if (m_position < m_data.size()) { + size_t delta = std::min(m_data.size() - m_position, length); + memmove(reinterpret_cast(&m_data[m_position]), data, delta); + data += delta; + length -= delta; + m_position += delta; + } - if (length != 0) - { - size_t insertPos = m_data.size(); - m_data.resize(insertPos + length); - memmove(reinterpret_cast(&m_data[insertPos]), data, length); - m_position += length; - } + if (length != 0) { + size_t insertPos = m_data.size(); + m_data.resize(insertPos + length); + memmove(reinterpret_cast(&m_data[insertPos]), data, length); + m_position += length; + } } -} // Athena +} // namespace athena::io diff --git a/src/athena/WiiBanner.cpp b/src/athena/WiiBanner.cpp index c8a5df3..dc215c3 100644 --- a/src/athena/WiiBanner.cpp +++ b/src/athena/WiiBanner.cpp @@ -4,138 +4,71 @@ #include "athena/Utility.hpp" #include -namespace athena -{ +namespace athena { -WiiBanner::WiiBanner() : - m_gameId(0), - m_banner(NULL), - m_flags(0), - m_bannerSize(0) -{ +WiiBanner::WiiBanner() : m_gameId(0), m_banner(NULL), m_flags(0), m_bannerSize(0) {} + +WiiBanner::WiiBanner(atUint32 gameId, const std::u16string& title, const std::u16string& subtitle, WiiImage* banner, + std::vector icons) +: m_gameId(gameId) +, m_banner(banner) +, m_flags(0) +, m_bannerSize(0) +, m_icons(icons) +, m_title(title) +, m_subtitle(subtitle) {} + +WiiBanner::~WiiBanner() { + delete m_banner; + m_icons.clear(); } -WiiBanner::WiiBanner(atUint32 gameId, const std::u16string& title, - const std::u16string& subtitle, WiiImage* banner, std::vector icons) : - m_gameId(gameId), - m_banner(banner), - m_flags(0), - m_bannerSize(0), - m_icons(icons), - m_title(title), - m_subtitle(subtitle) -{ +void WiiBanner::setGameID(atUint64 id) { m_gameId = id; } + +atUint64 WiiBanner::gameID() const { return m_gameId; } +void WiiBanner::setTitle(const std::u16string& title) { m_title = title; } + +const std::u16string& WiiBanner::title() const { return m_title; } + +void WiiBanner::setSubtitle(const std::u16string& subtitle) { m_subtitle = subtitle; } + +const std::u16string& WiiBanner::subtitle() const { return m_subtitle; } + +void WiiBanner::addIcon(WiiImage* icon) { m_icons.push_back(icon); } + +void WiiBanner::setIcon(atUint32 id, WiiImage* icon) { + if (m_icons[id] != NULL) { + delete m_icons[id]; + m_icons[id] = icon; + } } -WiiBanner::~WiiBanner() -{ - delete m_banner; - m_icons.clear(); -} +WiiImage* WiiBanner::getIcon(atUint32 id) const { + if (!m_icons[id]) + return NULL; -void WiiBanner::setGameID(atUint64 id) -{ - m_gameId = id; + return m_icons[id]; } +std::vector WiiBanner::icons() const { return m_icons; } -atUint64 WiiBanner::gameID() const -{ - return m_gameId; -} -void WiiBanner::setTitle(const std::u16string& title) -{ - m_title = title; -} +void WiiBanner::setBannerImage(WiiImage* banner) { m_banner = banner; } -const std::u16string& WiiBanner::title() const -{ - return m_title; -} +WiiImage* WiiBanner::bannerImage() const { return m_banner; } -void WiiBanner::setSubtitle(const std::u16string& subtitle) -{ - m_subtitle = subtitle; -} +void WiiBanner::setAnimationSpeed(atUint16 animSpeed) { m_animSpeed = animSpeed; } -const std::u16string& WiiBanner::subtitle() const -{ - return m_subtitle; -} +atUint16 WiiBanner::animationSpeed() const { return m_animSpeed; } -void WiiBanner::addIcon(WiiImage* icon) -{ - m_icons.push_back(icon); -} +void WiiBanner::setPermissions(atUint8 permissions) { m_permissions = permissions; } -void WiiBanner::setIcon(atUint32 id, WiiImage* icon) -{ - if (m_icons[id] != NULL) - { - delete m_icons[id]; - m_icons[id] = icon; - } -} +atUint8 WiiBanner::permissions() const { return m_permissions; } -WiiImage* WiiBanner::getIcon(atUint32 id) const -{ - if (!m_icons[id]) - return NULL; +void WiiBanner::setBannerSize(atUint32 size) { m_bannerSize = size; } - return m_icons[id]; -} -std::vector WiiBanner::icons() const -{ - return m_icons; -} +atUint32 WiiBanner::bannerSize() const { return m_bannerSize; } -void WiiBanner::setBannerImage(WiiImage* banner) -{ - m_banner = banner; -} +void WiiBanner::setFlags(atUint32 flags) { m_flags = flags; } -WiiImage* WiiBanner::bannerImage() const -{ - return m_banner; -} +atUint32 WiiBanner::flags() const { return m_flags; } -void WiiBanner::setAnimationSpeed(atUint16 animSpeed) -{ - m_animSpeed = animSpeed; -} - -atUint16 WiiBanner::animationSpeed() const -{ - return m_animSpeed; -} - -void WiiBanner::setPermissions(atUint8 permissions) -{ - m_permissions = permissions; -} - -atUint8 WiiBanner::permissions() const -{ - return m_permissions; -} - -void WiiBanner::setBannerSize(atUint32 size) -{ - m_bannerSize = size; -} - -atUint32 WiiBanner::bannerSize() const -{ - return m_bannerSize; -} - -void WiiBanner::setFlags(atUint32 flags) -{ - m_flags = flags; -} - -atUint32 WiiBanner::flags() const -{ - return m_flags; -} - -} // zelda +} // namespace athena diff --git a/src/athena/WiiFile.cpp b/src/athena/WiiFile.cpp index ce9d379..a0eccfb 100644 --- a/src/athena/WiiFile.cpp +++ b/src/athena/WiiFile.cpp @@ -2,276 +2,209 @@ #include "athena/Utility.hpp" #include -namespace athena -{ +namespace athena { //! TODO: Remove this? -WiiFile::WiiFile() : - m_permissions(WiiFile::GroupRW | WiiFile::OtherRW | WiiFile::OwnerRW), - m_attributes(0), - m_type(WiiFile::File), - m_filename(""), - m_fileLen(0), - m_fileData(NULL), - m_parent(NULL) -{ - //ctor +WiiFile::WiiFile() +: m_permissions(WiiFile::GroupRW | WiiFile::OtherRW | WiiFile::OwnerRW) +, m_attributes(0) +, m_type(WiiFile::File) +, m_filename("") +, m_fileLen(0) +, m_fileData(NULL) +, m_parent(NULL) { + // ctor } -WiiFile::WiiFile(const std::string& filename) : - m_permissions(WiiFile::GroupRW | WiiFile::OtherRW | WiiFile::OwnerRW), - m_attributes(0), - m_type(WiiFile::File), - m_filename(filename), - m_fileLen(0), - m_fileData(NULL), - m_parent(NULL) -{ +WiiFile::WiiFile(const std::string& filename) +: m_permissions(WiiFile::GroupRW | WiiFile::OtherRW | WiiFile::OwnerRW) +, m_attributes(0) +, m_type(WiiFile::File) +, m_filename(filename) +, m_fileLen(0) +, m_fileData(NULL) +, m_parent(NULL) {} + +WiiFile::WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length) +: m_permissions(permissions) +, m_attributes(0) +, m_type(WiiFile::File) +, m_filename(filename) +, m_fileLen(length) +, m_fileData((atUint8*)data) {} + +WiiFile::~WiiFile() { + if (m_fileData) + delete[] m_fileData; + + for (WiiFile* child : m_children) + delete child; } -WiiFile::WiiFile(const std::string& filename, atUint8 permissions, const atUint8* data, atUint32 length) : - m_permissions(permissions), - m_attributes(0), - m_type(WiiFile::File), - m_filename(filename), - m_fileLen(length), - m_fileData((atUint8*)data) -{ +void WiiFile::setFilename(const std::string& filename) { m_filename = filename; } + +std::string WiiFile::filename() const { return m_filename; } + +void WiiFile::setPermissions(const atUint8 permissions) { m_permissions = (atUint8)permissions; } + +atUint8 WiiFile::permissions() const { return m_permissions; } + +void WiiFile::setData(const atUint8* data) { + if (m_fileData) { + delete[] m_fileData; + m_fileData = NULL; + } + + m_fileData = (atUint8*)data; } -WiiFile::~WiiFile() -{ - if (m_fileData) - delete[] m_fileData; +atUint8* WiiFile::data() const { return m_fileData; } - for (WiiFile* child : m_children) - delete child; -} +void WiiFile::setLength(const int len) { m_fileLen = (int)len; } +int WiiFile::length() const { return m_fileLen; } -void WiiFile::setFilename(const std::string& filename) -{ - m_filename = filename; -} +void WiiFile::setAttributes(const atUint8 attr) { m_attributes = attr; } -std::string WiiFile::filename() const -{ - return m_filename; -} +atUint8 WiiFile::attributes() const { return m_attributes; } -void WiiFile::setPermissions(const atUint8 permissions) -{ - m_permissions = (atUint8)permissions; -} +void WiiFile::setType(WiiFile::Type type) { m_type = type; } -atUint8 WiiFile::permissions() const -{ - return m_permissions; -} +WiiFile::Type WiiFile::type() const { return m_type; } -void WiiFile::setData(const atUint8* data) -{ - if (m_fileData) - { - delete[] m_fileData; - m_fileData = NULL; +bool WiiFile::isDirectory() const { return (m_type == WiiFile::Directory); } + +bool WiiFile::isFile() const { return (m_type == WiiFile::File); } + +void WiiFile::addChild(WiiFile* file) { + if (!isDirectory()) { + atWarning("%s is not a directory", filename().c_str()); + return; + } + + if (std::find(m_children.begin(), m_children.end(), file) != m_children.end()) + return; + + // Lets figure out it's place + std::string tmpName(file->filename()); + // Since we only support *NIX paths this is simple + atUint32 depth = athena::utility::countChar(tmpName, '/'); + bool owned = false; + + while ((depth--) > 0) { + // add them from the beginning of the path up + tmpName = tmpName.substr(0, tmpName.find('/')); + + for (atUint32 i = 0; i < m_children.size(); i++) { + if (!m_children[i]->filename().compare(tmpName)) { + std::string newName = file->filename(); + newName = newName.substr(newName.rfind("/") + 1, newName.size() - newName.rfind("/")); + file->setFilename(newName); + m_children[i]->addChild(file); + owned = true; + } } + } - m_fileData = (atUint8*)data; + if (!owned) { + m_children.push_back(file); + file->setParent(this); + } } -atUint8* WiiFile::data() const -{ - return m_fileData; +WiiFile* WiiFile::child(const std::string& name) { + std::vector::iterator iter = + std::find_if(m_children.begin(), m_children.end(), [&name](WiiFile* f) { return !f->filename().compare(name); }); + + if (iter != m_children.end()) + return *iter; + + std::string tmpName(name); + tmpName = tmpName.substr(tmpName.rfind('/') + 1, tmpName.size() - tmpName.rfind('/')); + + for (WiiFile* f : m_children) { + if (f->isFile()) + continue; + + WiiFile* ret = f->child(tmpName); + + if (ret) + return ret; + } + + return nullptr; } -void WiiFile::setLength(const int len) -{ - m_fileLen = (int)len; +void WiiFile::removeChild(WiiFile* file) { + std::vector::iterator iter = std::find(m_children.begin(), m_children.end(), file); + + if (iter == m_children.end()) + return; + + m_children.erase(iter); } -int WiiFile::length() const -{ - return m_fileLen; +WiiFile* WiiFile::parent() { return m_parent; } + +void WiiFile::setParent(WiiFile* parent) { + if (m_parent) + m_parent->removeChild(this); + + m_parent = parent; + m_parent->addChild(this); } -void WiiFile::setAttributes(const atUint8 attr) -{ - m_attributes = attr; +atUint32 WiiFile::fileCount() { + size_t ret = m_children.size(); + + for (WiiFile* f : m_children) { + if (f->isFile()) + continue; + + ret += f->fileCount(); + } + + return (atUint32)ret; } -atUint8 WiiFile::attributes() const -{ - return m_attributes; -} - -void WiiFile::setType(WiiFile::Type type) -{ - m_type = type; -} - -WiiFile::Type WiiFile::type() const -{ - return m_type; -} - -bool WiiFile::isDirectory() const -{ - return (m_type == WiiFile::Directory); -} - -bool WiiFile::isFile() const -{ - return (m_type == WiiFile::File); -} - -void WiiFile::addChild(WiiFile* file) -{ - if (!isDirectory()) - { - atWarning("%s is not a directory", filename().c_str()); - return; - } - - if (std::find(m_children.begin(), m_children.end(), file) != m_children.end()) - return; - - // Lets figure out it's place - std::string tmpName(file->filename()); - // Since we only support *NIX paths this is simple - atUint32 depth = athena::utility::countChar(tmpName, '/'); - bool owned = false; - - while ((depth--) > 0) - { - // add them from the beginning of the path up - tmpName = tmpName.substr(0, tmpName.find('/')); - - for (atUint32 i = 0; i < m_children.size(); i++) - { - if (!m_children[i]->filename().compare(tmpName)) - { - std::string newName = file->filename(); - newName = newName.substr(newName.rfind("/") + 1, newName.size() - newName.rfind("/")); - file->setFilename(newName); - m_children[i]->addChild(file); - owned = true; - } - } - } - - if (!owned) - { - m_children.push_back(file); - file->setParent(this); - } -} - -WiiFile* WiiFile::child(const std::string& name) -{ - std::vector::iterator iter = std::find_if(m_children.begin(), m_children.end(), - [&name](WiiFile * f) { return !f->filename().compare(name); }); - - if (iter != m_children.end()) - return *iter; - - std::string tmpName(name); - tmpName = tmpName.substr(tmpName.rfind('/') + 1, tmpName.size() - tmpName.rfind('/')); - - for (WiiFile* f : m_children) - { - if (f->isFile()) - continue; - - WiiFile* ret = f->child(tmpName); - - if (ret) - return ret; - } - - return nullptr; -} - -void WiiFile::removeChild(WiiFile* file) -{ - std::vector::iterator iter = std::find(m_children.begin(), m_children.end(), file); - - if (iter == m_children.end()) - return; - - m_children.erase(iter); -} - -WiiFile* WiiFile::parent() -{ - return m_parent; -} - -void WiiFile::setParent(WiiFile* parent) -{ - if (m_parent) - m_parent->removeChild(this); - - m_parent = parent; - m_parent->addChild(this); -} - -atUint32 WiiFile::fileCount() -{ - size_t ret = m_children.size(); - - for (WiiFile* f : m_children) - { - if (f->isFile()) - continue; - - ret += f->fileCount(); - } - - return (atUint32)ret; -} - -std::vector WiiFile::allChildren() -{ - std::vector ret; - - if (m_children.size() == 0) - return ret; - - // Add our children first - for (WiiFile* f : m_children) - ret.push_back(f); - - // now lets add our children's children - for (WiiFile* f : m_children) - { - if (f->isFile()) - continue; - - std::vector tmp = f->allChildren(); - - if (tmp.size() == 0) - continue; - - ret.insert(ret.end(), tmp.begin(), tmp.end()); - } +std::vector WiiFile::allChildren() { + std::vector ret; + if (m_children.size() == 0) return ret; + + // Add our children first + for (WiiFile* f : m_children) + ret.push_back(f); + + // now lets add our children's children + for (WiiFile* f : m_children) { + if (f->isFile()) + continue; + + std::vector tmp = f->allChildren(); + + if (tmp.size() == 0) + continue; + + ret.insert(ret.end(), tmp.begin(), tmp.end()); + } + + return ret; } -std::string WiiFile::fullpath() -{ - std::string ret; +std::string WiiFile::fullpath() { + std::string ret; - if (m_parent) - ret = m_parent->filename() + "/"; + if (m_parent) + ret = m_parent->filename() + "/"; - ret = ret + filename(); + ret = ret + filename(); - while (ret.at(0) == '/') - ret.erase(ret.begin()); + while (ret.at(0) == '/') + ret.erase(ret.begin()); - return ret; + return ret; } -} // zelda +} // namespace athena diff --git a/src/athena/WiiImage.cpp b/src/athena/WiiImage.cpp index c6d51f0..a8e8a3f 100644 --- a/src/athena/WiiImage.cpp +++ b/src/athena/WiiImage.cpp @@ -3,82 +3,60 @@ #include #include -namespace athena -{ +namespace athena { -WiiImage::WiiImage(atUint32 width, atUint32 height, std::unique_ptr&& data) : - m_width(width), - m_height(height), - m_data(std::move(data)) -{ -} +WiiImage::WiiImage(atUint32 width, atUint32 height, std::unique_ptr&& data) +: m_width(width), m_height(height), m_data(std::move(data)) {} -atUint8* WiiImage::data() -{ - return m_data.get(); -} +atUint8* WiiImage::data() { return m_data.get(); } -atUint32 WiiImage::width() const -{ - return m_width; -} +atUint32 WiiImage::width() const { return m_width; } -atUint32 WiiImage::height() const -{ - return m_height; -} +atUint32 WiiImage::height() const { return m_height; } -atUint8* WiiImage::toRGBA() -{ - atUint32 x, y; - atUint32 x1, y1; - atUint32 iv; - atUint8* bitmapdata = NULL; +atUint8* WiiImage::toRGBA() { + atUint32 x, y; + atUint32 x1, y1; + atUint32 iv; + atUint8* bitmapdata = NULL; - bitmapdata = new atUint8[m_width * m_height * 4]; + bitmapdata = new atUint8[m_width * m_height * 4]; - if (bitmapdata == NULL) - return NULL; + if (bitmapdata == NULL) + return NULL; - for (iv = 0, y1 = 0; y1 < m_height; y1 += 4) - { - for (x1 = 0; x1 < m_width; x1 += 4) - { - for (y = y1; y < (y1 + 4); y++) - { - for (x = x1; x < (x1 + 4); x++) - { - atUint16 oldpixel = *(atUint16*)(m_data.get() + ((iv++) * 2)); - //if((x >= m_width) || (y >= m_height)) - // continue; - oldpixel = utility::swapU16(oldpixel); + for (iv = 0, y1 = 0; y1 < m_height; y1 += 4) { + for (x1 = 0; x1 < m_width; x1 += 4) { + for (y = y1; y < (y1 + 4); y++) { + for (x = x1; x < (x1 + 4); x++) { + atUint16 oldpixel = *(atUint16*)(m_data.get() + ((iv++) * 2)); + // if((x >= m_width) || (y >= m_height)) + // continue; + oldpixel = utility::swapU16(oldpixel); - if (oldpixel & (1 << 15)) - { - // RGB5 - atUint8 b = (((oldpixel >> 10) & 0x1F) * 255) / 31; - atUint8 g = (((oldpixel >> 5) & 0x1F) * 255) / 31; - atUint8 r = (((oldpixel >> 0) & 0x1F) * 255) / 31; - atUint8 a = 255; - atUint8 rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24); - (*(atUint32**)&bitmapdata)[x + (y * m_width)] = rgba; - } - else - { - // RGB4A3 - atUint8 a = (((oldpixel >> 12) & 0x7) * 255) / 7; - atUint8 b = (((oldpixel >> 8) & 0xF) * 255) / 15; - atUint8 g = (((oldpixel >> 4) & 0xF) * 255) / 15; - atUint8 r = (((oldpixel >> 0) & 0xF) * 255) / 15; - atUint32 rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24); - (*(atUint32**)&bitmapdata)[x + (y * m_width)] = rgba; - } - } - } + if (oldpixel & (1 << 15)) { + // RGB5 + atUint8 b = (((oldpixel >> 10) & 0x1F) * 255) / 31; + atUint8 g = (((oldpixel >> 5) & 0x1F) * 255) / 31; + atUint8 r = (((oldpixel >> 0) & 0x1F) * 255) / 31; + atUint8 a = 255; + atUint8 rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24); + (*(atUint32**)&bitmapdata)[x + (y * m_width)] = rgba; + } else { + // RGB4A3 + atUint8 a = (((oldpixel >> 12) & 0x7) * 255) / 7; + atUint8 b = (((oldpixel >> 8) & 0xF) * 255) / 15; + atUint8 g = (((oldpixel >> 4) & 0xF) * 255) / 15; + atUint8 r = (((oldpixel >> 0) & 0xF) * 255) / 15; + atUint32 rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24); + (*(atUint32**)&bitmapdata)[x + (y * m_width)] = rgba; + } } + } } + } - return bitmapdata; + return bitmapdata; } -} // zelda +} // namespace athena diff --git a/src/athena/WiiSave.cpp b/src/athena/WiiSave.cpp index 7ab4d8a..c86872b 100644 --- a/src/athena/WiiSave.cpp +++ b/src/athena/WiiSave.cpp @@ -12,74 +12,49 @@ #include #include - -namespace athena -{ +namespace athena { WiiSave::WiiSave() - : m_root(NULL), - m_banner(NULL) +: m_root(NULL) +, m_banner(NULL) -{ +{} + +WiiSave::~WiiSave() { + delete m_root; + delete m_banner; + m_banner = NULL; } -WiiSave::~WiiSave() -{ +void WiiSave::addFile(WiiFile* file) { m_root->addChild(file); } + +void WiiSave::setRoot(WiiFile* root) { + if (root != m_root) delete m_root; - delete m_banner; - m_banner = NULL; + m_root = root; } -void WiiSave::addFile(WiiFile* file) -{ - m_root->addChild(file); +WiiFile* WiiSave::file(const std::string& filepath) { + if (filepath.empty()) + return nullptr; + + std::string cleanPath(filepath); + + while (cleanPath.at(0) == '/') + cleanPath.erase(cleanPath.begin()); + + return m_root->child(cleanPath); } -void WiiSave::setRoot(WiiFile* root) -{ - if (root != m_root) - delete m_root; +atUint32 WiiSave::fileCount() const { return m_root->fileCount(); } - m_root = root; -} +WiiFile* WiiSave::root() { return m_root; } -WiiFile* WiiSave::file(const std::string& filepath) -{ - if (filepath.empty()) - return nullptr; +void WiiSave::setBanner(WiiBanner* banner) { m_banner = banner; } - std::string cleanPath(filepath); +WiiBanner* WiiSave::banner() const { return m_banner; } - while (cleanPath.at(0) == '/') - cleanPath.erase(cleanPath.begin()); +std::vector WiiSave::allFiles() const { return m_root->allChildren(); } - return m_root->child(cleanPath); -} - -atUint32 WiiSave::fileCount() const -{ - return m_root->fileCount(); -} - -WiiFile* WiiSave::root() -{ - return m_root; -} - -void WiiSave::setBanner(WiiBanner* banner) -{ - m_banner = banner; -} - -WiiBanner* WiiSave::banner() const -{ - return m_banner; -} - -std::vector WiiSave::allFiles() const -{ - return m_root->allChildren(); -} - -} // zelda +} // namespace athena diff --git a/src/athena/WiiSaveReader.cpp b/src/athena/WiiSaveReader.cpp index c95c2c7..ff9df7c 100644 --- a/src/athena/WiiSaveReader.cpp +++ b/src/athena/WiiSaveReader.cpp @@ -13,320 +13,291 @@ #include #include -namespace athena -{ +namespace athena { -namespace io -{ +namespace io { -WiiSaveReader::WiiSaveReader(const atUint8* data, atUint64 length) - : MemoryCopyReader(data, length) -{ - setEndian(Endian::Big); +WiiSaveReader::WiiSaveReader(const atUint8* data, atUint64 length) : MemoryCopyReader(data, length) { + setEndian(Endian::Big); } -WiiSaveReader::WiiSaveReader(const std::string& filename) - : MemoryCopyReader(filename) -{ - setEndian(Endian::Big); +WiiSaveReader::WiiSaveReader(const std::string& filename) : MemoryCopyReader(filename) { setEndian(Endian::Big); } + +std::unique_ptr WiiSaveReader::readSave() { + WiiSave* ret = new WiiSave; + + if (length() < 0xF0C0) { + atError("Not a valid WiiSave"); + return nullptr; + } + + WiiBanner* banner = this->readBanner(); + + if (!banner) { + atError("Invalid banner"); + return nullptr; + } + + ret->setBanner(banner); + atUint32 bkVer = readUint32(); + + if (bkVer != 0x00000070) { + atError("Invalid BacKup header size"); + return nullptr; + } + + atUint32 bkMagic = readUint32(); + + if (bkMagic != 0x426B0001) { + atError("Invalid BacKup header magic"); + return nullptr; + } + + /*atUint32 ngId =*/readUint32(); + atUint32 numFiles = readUint32(); + + /*int fileSize =*/readUint32(); + seek(8); // skip unknown data; + + atUint32 totalSize = readUint32(); + seek(64); // Unknown (Most likely padding) + seek(8); + seek(6); + seek(2); + seek(0x10); + + std::vector files; + + for (atUint32 i = 0; i < numFiles; ++i) { + WiiFile* file = readFile(); + + if (file) + files.push_back(file); + } + + ret->setRoot(buildTree(files)); + + readCerts(totalSize); + return std::unique_ptr(ret); } -std::unique_ptr WiiSaveReader::readSave() -{ - WiiSave* ret = new WiiSave; +WiiBanner* WiiSaveReader::readBanner() { + atUint8* dec = new atUint8[0xF0C0]; + memset(dec, 0, 0xF0C0); + std::unique_ptr buf = readUBytes(0xF0C0); + atUint8* oldData = data(); + atUint64 oldPos = position(); + atUint64 oldLen = length(); + atUint64 gameId; + atUint32 bannerSize; + atUint8 permissions; + atUint8 md5[16]; + atUint8 md5Calc[16]; + atUint8 tmpIV[16]; + memcpy(tmpIV, SD_IV, 16); - if (length() < 0xF0C0) - { - atError("Not a valid WiiSave"); - return nullptr; - } + std::cout << "Decrypting: banner.bin..."; + std::unique_ptr aes = NewAES(); + aes->setKey(SD_KEY); + aes->decrypt(tmpIV, buf.get(), dec, 0xF0C0); + std::cout << "done" << std::endl; - WiiBanner* banner = this->readBanner(); + memset(md5, 0, 16); + memset(md5Calc, 0, 16); + // Read in the MD5 sum + memcpy(md5, (dec + 0x0E), 0x10); + // Write the blanker to the buffer + memcpy((dec + 0x0E), MD5_BLANKER, 0x10); + MD5Hash::MD5(md5Calc, dec, 0xF0C0); - if (!banner) - { - atError("Invalid banner"); - return nullptr; - } + // Compare the Calculated MD5 to the one from the file. + // This needs to be done incase the file is corrupted. + if (memcmp(md5, md5Calc, 0x10)) { + std::cerr << "MD5 Mismatch" << std::endl; + // Make sure to reset m_reader values back to the old ones. + std::cerr << "MD5 provided: "; - ret->setBanner(banner); - atUint32 bkVer = readUint32(); + for (int i = 0; i < 16; ++i) + std::cerr << std::setw(2) << std::setfill('0') << std::hex << (int)(md5[i]); - if (bkVer != 0x00000070) - { - atError("Invalid BacKup header size"); - return nullptr; - } + std::cerr << std::endl; - atUint32 bkMagic = readUint32(); + std::cerr << "MD5 Calculated: "; - if (bkMagic != 0x426B0001) - { - atError("Invalid BacKup header magic"); - return nullptr; - } - - /*atUint32 ngId =*/ readUint32(); - atUint32 numFiles = readUint32(); - - /*int fileSize =*/ readUint32(); - seek(8); // skip unknown data; - - atUint32 totalSize = readUint32(); - seek(64); // Unknown (Most likely padding) - seek(8); - seek(6); - seek(2); - seek(0x10); - - std::vector files; - - for (atUint32 i = 0; i < numFiles; ++i) - { - WiiFile* file = readFile(); - - if (file) - files.push_back(file); - } - - ret->setRoot(buildTree(files)); - - readCerts(totalSize); - return std::unique_ptr(ret); -} - -WiiBanner* WiiSaveReader::readBanner() -{ - atUint8* dec = new atUint8[0xF0C0]; - memset(dec, 0, 0xF0C0); - std::unique_ptr buf = readUBytes(0xF0C0); - atUint8* oldData = data(); - atUint64 oldPos = position(); - atUint64 oldLen = length(); - atUint64 gameId; - atUint32 bannerSize; - atUint8 permissions; - atUint8 md5[16]; - atUint8 md5Calc[16]; - atUint8 tmpIV[16]; - memcpy(tmpIV, SD_IV, 16); - - std::cout << "Decrypting: banner.bin..."; - std::unique_ptr aes = NewAES(); - aes->setKey(SD_KEY); - aes->decrypt(tmpIV, buf.get(), dec, 0xF0C0); - std::cout << "done" << std::endl; - - memset(md5, 0, 16); - memset(md5Calc, 0, 16); - // Read in the MD5 sum - memcpy(md5, (dec + 0x0E), 0x10); - // Write the blanker to the buffer - memcpy((dec + 0x0E), MD5_BLANKER, 0x10); - MD5Hash::MD5(md5Calc, dec, 0xF0C0); - - // Compare the Calculated MD5 to the one from the file. - // This needs to be done incase the file is corrupted. - if (memcmp(md5, md5Calc, 0x10)) - { - std::cerr << "MD5 Mismatch" << std::endl; - // Make sure to reset m_reader values back to the old ones. - std::cerr << "MD5 provided: "; - - for (int i = 0; i < 16; ++i) - std::cerr << std::setw(2) << std::setfill('0') << std::hex << (int)(md5[i]); - - std::cerr << std::endl; - - std::cerr << "MD5 Calculated: "; - - for (int i = 0; i < 16; ++i) - std::cerr << std::hex << (int)(md5Calc[i]); - - std::cerr << std::endl; - setData(oldData, oldLen); - seek(oldPos, SeekOrigin::Begin); - atError("MD5 Mismatch"); - return nullptr; - } - - // Set the binary reader buffer; - setData(dec, 0xF0C0); - // Start reading the header - gameId = readUint64(); - bannerSize = readUint32(); - permissions = readByte(); - /* unk =*/ readByte(); - seek(0x10); - // skip padding - seek(2); - - int magic; - int flags; - short animSpeed; - std::u16string gameTitle; - std::u16string subTitle; - - magic = readUint32(); - - // Ensure that the header magic is valid. - if (magic != 0x5749424E) - { - // Make sure to reset m_reader values back to the old ones. - setData(oldData, oldLen); - seek(oldPos, SeekOrigin::Begin); - atError("Invalid Header Magic"); - return nullptr; - } - - flags = readUint32(); - animSpeed = readUint16(); - seek(22); - - gameTitle = readU16StringBig(); - - if (position() != 0x0080) - seek(0x0080, SeekOrigin::Begin); - - subTitle = readU16StringBig(); - - if (position() != 0x00C0) - seek(0x00C0, SeekOrigin::Begin); - - WiiBanner* banner = new WiiBanner; - banner->setGameID(gameId); - banner->setTitle(gameTitle); - banner->setSubtitle(subTitle); - banner->setBannerSize(bannerSize); - WiiImage* bannerImage = readImage(192, 64); - banner->setBannerImage(bannerImage); - banner->setAnimationSpeed(animSpeed); - banner->setPermissions(permissions); - banner->setFlags(flags); - - - if (banner->bannerSize() == 0x72a0) - { - WiiImage* icon = readImage(48, 48); - - if (icon) - banner->addIcon(icon); - else - std::cerr << "Warning: Icon empty, skipping" << std::endl; - } - else - { - for (int i = 0; i < 8; i++) - { - WiiImage* icon = readImage(48, 48); - - if (icon) - banner->addIcon(icon); - else - std::cerr << "Warning: Icon empty, skipping" << std::endl; - } - } + for (int i = 0; i < 16; ++i) + std::cerr << std::hex << (int)(md5Calc[i]); + std::cerr << std::endl; setData(oldData, oldLen); seek(oldPos, SeekOrigin::Begin); - return banner; + atError("MD5 Mismatch"); + return nullptr; + } + + // Set the binary reader buffer; + setData(dec, 0xF0C0); + // Start reading the header + gameId = readUint64(); + bannerSize = readUint32(); + permissions = readByte(); + /* unk =*/readByte(); + seek(0x10); + // skip padding + seek(2); + + int magic; + int flags; + short animSpeed; + std::u16string gameTitle; + std::u16string subTitle; + + magic = readUint32(); + + // Ensure that the header magic is valid. + if (magic != 0x5749424E) { + // Make sure to reset m_reader values back to the old ones. + setData(oldData, oldLen); + seek(oldPos, SeekOrigin::Begin); + atError("Invalid Header Magic"); + return nullptr; + } + + flags = readUint32(); + animSpeed = readUint16(); + seek(22); + + gameTitle = readU16StringBig(); + + if (position() != 0x0080) + seek(0x0080, SeekOrigin::Begin); + + subTitle = readU16StringBig(); + + if (position() != 0x00C0) + seek(0x00C0, SeekOrigin::Begin); + + WiiBanner* banner = new WiiBanner; + banner->setGameID(gameId); + banner->setTitle(gameTitle); + banner->setSubtitle(subTitle); + banner->setBannerSize(bannerSize); + WiiImage* bannerImage = readImage(192, 64); + banner->setBannerImage(bannerImage); + banner->setAnimationSpeed(animSpeed); + banner->setPermissions(permissions); + banner->setFlags(flags); + + if (banner->bannerSize() == 0x72a0) { + WiiImage* icon = readImage(48, 48); + + if (icon) + banner->addIcon(icon); + else + std::cerr << "Warning: Icon empty, skipping" << std::endl; + } else { + for (int i = 0; i < 8; i++) { + WiiImage* icon = readImage(48, 48); + + if (icon) + banner->addIcon(icon); + else + std::cerr << "Warning: Icon empty, skipping" << std::endl; + } + } + + setData(oldData, oldLen); + seek(oldPos, SeekOrigin::Begin); + return banner; } -WiiImage* WiiSaveReader::readImage(atUint32 width, atUint32 height) -{ - std::unique_ptr image = readUBytes(width * height * 2); +WiiImage* WiiSaveReader::readImage(atUint32 width, atUint32 height) { + std::unique_ptr image = readUBytes(width * height * 2); - if (!utility::isEmpty((atInt8*)image.get(), width * height * 2)) - return new WiiImage(width, height, std::move(image)); + if (!utility::isEmpty((atInt8*)image.get(), width * height * 2)) + return new WiiImage(width, height, std::move(image)); + return NULL; +} + +WiiFile* WiiSaveReader::readFile() { + atUint32 fileLen; + atUint8 permissions; + atUint8 attributes; + atUint8 type; + std::string name; + WiiFile* ret; + + atUint32 magic = readUint32(); + + if (magic != 0x03adf17e) { + std::cerr << "Not a valid File entry header: 0x" << std::hex << magic << std::endl; return NULL; + } + + fileLen = readUint32(); + permissions = readByte(); + attributes = readByte(); + type = (WiiFile::Type)readByte(); + name = std::string((const char*)readBytes(0x45).get()); + ret = new WiiFile(std::string(name)); + ret->setPermissions(permissions); + ret->setAttributes(attributes); + ret->setType((WiiFile::Type)type); + std::unique_ptr iv = readUBytes(0x10); + seek(0x20); + + if (type == WiiFile::File) { + // Read file data + int roundedLen = (fileLen + 63) & ~63; + std::unique_ptr filedata = readUBytes(roundedLen); + + // Decrypt file + std::cout << "Decrypting: " << ret->filename() << "..."; + atUint8* decData = new atUint8[roundedLen]; + std::unique_ptr aes = NewAES(); + aes->setKey(SD_KEY); + aes->decrypt(iv.get(), filedata.get(), decData, roundedLen); + ret->setData(decData); + ret->setLength(fileLen); + std::cout << "done" << std::endl; + } + + return ret; } +void WiiSaveReader::readCerts(atUint32 totalSize) { + std::cout << "Reading certs..." << std::endl; + atUint32 dataSize = totalSize - 0x340; + std::unique_ptr sig = readUBytes(0x40); + std::unique_ptr ngCert = readUBytes(0x180); + std::unique_ptr apCert = readUBytes(0x180); + seek(0xF0C0, SeekOrigin::Begin); + std::unique_ptr data = readUBytes(dataSize); + atUint8* hash; -WiiFile* WiiSaveReader::readFile() -{ - atUint32 fileLen; - atUint8 permissions; - atUint8 attributes; - atUint8 type; - std::string name; - WiiFile* ret; + std::cout << "validating..." << std::endl; + hash = getSha1(data.get(), dataSize); + atUint8* hash2 = getSha1(hash, 20); + bool ngValid = false; + bool apValid = false; + ecc::checkEC(ngCert.get(), apCert.get(), sig.get(), hash2, apValid, ngValid); - atUint32 magic = readUint32(); - - if (magic != 0x03adf17e) - { - std::cerr << "Not a valid File entry header: 0x" << std::hex << magic << std::endl; - return NULL; - } - - fileLen = readUint32(); - permissions = readByte(); - attributes = readByte(); - type = (WiiFile::Type)readByte(); - name = std::string((const char*)readBytes(0x45).get()); - ret = new WiiFile(std::string(name)); - ret->setPermissions(permissions); - ret->setAttributes(attributes); - ret->setType((WiiFile::Type)type); - std::unique_ptr iv = readUBytes(0x10); - seek(0x20); - - if (type == WiiFile::File) - { - // Read file data - int roundedLen = (fileLen + 63) & ~63; - std::unique_ptr filedata = readUBytes(roundedLen); - - // Decrypt file - std::cout << "Decrypting: " << ret->filename() << "..."; - atUint8* decData = new atUint8[roundedLen]; - std::unique_ptr aes = NewAES(); - aes->setKey(SD_KEY); - aes->decrypt(iv.get(), filedata.get(), decData, roundedLen); - ret->setData(decData); - ret->setLength(fileLen); - std::cout << "done" << std::endl; - } - - return ret; + if (apValid) + std::cout << "AP Certificate ok" << std::endl; + if (ngValid) + std::cout << "NG Certificate ok" << std::endl; } -void WiiSaveReader::readCerts(atUint32 totalSize) -{ - std::cout << "Reading certs..." << std::endl; - atUint32 dataSize = totalSize - 0x340; - std::unique_ptr sig = readUBytes(0x40); - std::unique_ptr ngCert = readUBytes(0x180); - std::unique_ptr apCert = readUBytes(0x180); - seek(0xF0C0, SeekOrigin::Begin); - std::unique_ptr data = readUBytes(dataSize); - atUint8* hash; +WiiFile* WiiSaveReader::buildTree(std::vector files) { + // This is simply a virtual root that will contain all the other nodes + WiiFile* root = new WiiFile(""); + root->setType(WiiFile::Directory); - std::cout << "validating..." << std::endl; - hash = getSha1(data.get(), dataSize); - atUint8* hash2 = getSha1(hash, 20); - bool ngValid = false; - bool apValid = false; - ecc::checkEC(ngCert.get(), apCert.get(), sig.get(), hash2, apValid, ngValid); + for (WiiFile* f : files) + root->addChild(f); - if (apValid) - std::cout << "AP Certificate ok" << std::endl; - if (ngValid) - std::cout << "NG Certificate ok" << std::endl; + return root; } -WiiFile* WiiSaveReader::buildTree(std::vector files) -{ - // This is simply a virtual root that will contain all the other nodes - WiiFile* root = new WiiFile(""); - root->setType(WiiFile::Directory); - - for (WiiFile* f : files) - root->addChild(f); - - return root; -} - -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/src/athena/WiiSaveWriter.cpp b/src/athena/WiiSaveWriter.cpp index 81a6feb..92318b0 100644 --- a/src/athena/WiiSaveWriter.cpp +++ b/src/athena/WiiSaveWriter.cpp @@ -21,235 +21,216 @@ #include #include -namespace athena -{ +namespace athena { -namespace io -{ +namespace io { -WiiSaveWriter::WiiSaveWriter(const std::string& filename) - : MemoryCopyWriter(filename) -{ - setEndian(Endian::Big); +WiiSaveWriter::WiiSaveWriter(const std::string& filename) : MemoryCopyWriter(filename) { setEndian(Endian::Big); } + +bool WiiSaveWriter::writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, + atUint32 ngKeyId, const std::string& filepath) { + if (!save) { + atError("save cannot be NULL"); + return false; + } + + if (filepath != "") + m_filepath = filepath; + + writeBanner(save->banner()); + + writeUint32(0x70); + writeUint32(0x426B0001); + writeUint32(ngId); // NG-ID + writeUint32(save->fileCount()); + writeUint32(0); // Size of files; + seek(8); + writeUint32(0); // totalSize + seek(64); + writeUint64(save->banner()->gameID()); + writeBytes((atInt8*)macAddress, 6); + seek(2); // unknown; + seek(0x10); // padding; + atUint32 totalSize = 0; + + for (WiiFile* file : save->allFiles()) { + totalSize += writeFile(file); + } + + atUint64 pos = position(); + // Write size data + seek(0xF0C0 + 0x10, SeekOrigin::Begin); + writeUint32(totalSize); + seek(0xF0C0 + 0x1C, SeekOrigin::Begin); + writeUint32(totalSize + 0x3c0); + seek(pos, SeekOrigin::Begin); + + writeCerts(totalSize, ngId, ngPriv, ngSig, ngKeyId); + + this->save(); + + return true; } +void WiiSaveWriter::writeBanner(WiiBanner* banner) { + setEndian(Endian::Big); + writeInt64(banner->gameID()); + writeInt32((0x60a0 + 0x1200) * (atUint32)banner->icons().size()); + writeByte((atInt8)banner->permissions()); + seek(1); + writeBytes((atInt8*)MD5_BLANKER, 16); + seek(2); + writeInt32(0x5749424E); // WIBN + writeInt32(banner->flags()); + writeInt16(banner->animationSpeed()); + seek(22); -bool WiiSaveWriter::writeSave(WiiSave* save, atUint8* macAddress, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId, const std::string& filepath) -{ - if (!save) - { - atError("save cannot be NULL"); - return false; + for (char16_t c : banner->title()) + writeUint16(c); + writeUint16(0); + + if (position() != 0x0080) + seek(0x0080, SeekOrigin::Begin); + + for (char16_t c : banner->subtitle()) + writeUint16(c); + writeUint16(0); + + if (position() != 0x00C0) + seek(0x00C0, SeekOrigin::Begin); + + WiiImage* bannerImage = banner->bannerImage(); + writeBytes((atInt8*)bannerImage->data(), bannerImage->width() * bannerImage->height() * 2); + + // For empty icons + atUint8* tmpIcon = new atUint8[48 * 48 * 2]; + memset(tmpIcon, 0, 48 * 48 * 2); + + for (atUint32 i = 0; i < 8; ++i) { + if (i < banner->icons().size()) { + writeImage(banner->icons()[i]); + } else { + writeBytes((atInt8*)tmpIcon, 48 * 48 * 2); } + } - if (filepath != "") - m_filepath = filepath; + delete[] tmpIcon; // delete tmp buffer; - writeBanner(save->banner()); + atUint8* hash = new atUint8[0x10]; + MD5Hash::MD5(hash, (atUint8*)data(), 0xF0C0); + seek(0x0E, SeekOrigin::Begin); + writeBytes((atInt8*)hash, 0x10); - writeUint32(0x70); - writeUint32(0x426B0001); - writeUint32(ngId); // NG-ID - writeUint32(save->fileCount()); - writeUint32(0); // Size of files; - seek(8); - writeUint32(0); // totalSize - seek(64); - writeUint64(save->banner()->gameID()); - writeBytes((atInt8*)macAddress, 6); - seek(2); // unknown; - seek(0x10); // padding; - atUint32 totalSize = 0; + std::unique_ptr aes = NewAES(); + aes->setKey(SD_KEY); + atUint8 data[0xF0C0]; + memcpy(data, this->data(), 0xF0C0); + atUint8 tmpIV[26]; + memcpy(tmpIV, SD_IV, 16); + aes->encrypt(tmpIV, data, data, 0xF0C0); - for (WiiFile* file : save->allFiles()) - { - totalSize += writeFile(file); - } - - atUint64 pos = position(); - // Write size data - seek(0xF0C0 + 0x10, SeekOrigin::Begin); - writeUint32(totalSize); - seek(0xF0C0 + 0x1C, SeekOrigin::Begin); - writeUint32(totalSize + 0x3c0); - seek(pos, SeekOrigin::Begin); - - writeCerts(totalSize, ngId, ngPriv, ngSig, ngKeyId); - - this->save(); - - return true; + seek(0, SeekOrigin::Begin); + writeBytes((atInt8*)data, 0xF0C0); + seek(0xF0C0, SeekOrigin::Begin); } -void WiiSaveWriter::writeBanner(WiiBanner* banner) -{ - setEndian(Endian::Big); - writeInt64(banner->gameID()); - writeInt32((0x60a0 + 0x1200) * (atUint32)banner->icons().size()); - writeByte((atInt8)banner->permissions()); - seek(1); - writeBytes((atInt8*)MD5_BLANKER, 16); - seek(2); - writeInt32(0x5749424E); // WIBN - writeInt32(banner->flags()); - writeInt16(banner->animationSpeed()); - seek(22); +atUint32 WiiSaveWriter::writeFile(WiiFile* file) { + atUint32 ret = 0x80; - for (char16_t c : banner->title()) - writeUint16(c); - writeUint16(0); + // Write the File magic + writeUint32(0x03ADF17E); + writeUint32(file->length()); + writeByte(file->permissions()); + writeByte(file->attributes()); + writeByte(file->type()); - if (position() != 0x0080) - seek(0x0080, SeekOrigin::Begin); + atUint8 name[0x45]; + utility::fillRandom(name, 0x45); + memcpy(name, file->fullpath().c_str(), file->fullpath().size()); + name[file->fullpath().size()] = '\0'; + writeBytes((atInt8*)name, 0x45); + atUint8 iv[16]; + utility::fillRandom(iv, 0x10); + writeBytes((atInt8*)iv, 0x10); + atUint8 crap[0x20]; + utility::fillRandom(crap, 0x20); + writeBytes((atInt8*)crap, 0x20); - for (char16_t c : banner->subtitle()) - writeUint16(c); - writeUint16(0); - - if (position() != 0x00C0) - seek(0x00C0, SeekOrigin::Begin); - - WiiImage* bannerImage = banner->bannerImage(); - writeBytes((atInt8*)bannerImage->data(), bannerImage->width()*bannerImage->height() * 2); - - // For empty icons - atUint8* tmpIcon = new atUint8[48 * 48 * 2]; - memset(tmpIcon, 0, 48 * 48 * 2); - - for (atUint32 i = 0; i < 8; ++i) - { - if (i < banner->icons().size()) - { - writeImage(banner->icons()[i]); - } - else - { - writeBytes((atInt8*)tmpIcon, 48 * 48 * 2); - } - } - - delete[] tmpIcon; // delete tmp buffer; - - atUint8* hash = new atUint8[0x10]; - MD5Hash::MD5(hash, (atUint8*)data(), 0xF0C0); - seek(0x0E, SeekOrigin::Begin); - writeBytes((atInt8*)hash, 0x10); + if (file->type() == WiiFile::File) { + int roundedSize = (file->length() + 63) & ~63; + atUint8* data = new atUint8[roundedSize]; + memset(data, 0, roundedSize); std::unique_ptr aes = NewAES(); aes->setKey(SD_KEY); - atUint8 data[0xF0C0]; - memcpy(data, this->data(), 0xF0C0); - atUint8 tmpIV[26]; - memcpy(tmpIV, SD_IV, 16); - aes->encrypt(tmpIV, data, data, 0xF0C0); + aes->encrypt(iv, file->data(), data, roundedSize); - seek(0, SeekOrigin::Begin); - writeBytes((atInt8*)data, 0xF0C0); - seek(0xF0C0, SeekOrigin::Begin); + writeBytes((atInt8*)data, roundedSize); + ret += roundedSize; + delete[] data; + } + + return ret; } -atUint32 WiiSaveWriter::writeFile(WiiFile* file) -{ - atUint32 ret = 0x80; - - // Write the File magic - writeUint32(0x03ADF17E); - writeUint32(file->length()); - writeByte(file->permissions()); - writeByte(file->attributes()); - writeByte(file->type()); - - atUint8 name[0x45]; - utility::fillRandom(name, 0x45); - memcpy(name, file->fullpath().c_str(), file->fullpath().size()); - name[file->fullpath().size()] = '\0'; - writeBytes((atInt8*)name, 0x45); - atUint8 iv[16]; - utility::fillRandom(iv, 0x10); - writeBytes((atInt8*)iv, 0x10); - atUint8 crap[0x20]; - utility::fillRandom(crap, 0x20); - writeBytes((atInt8*)crap, 0x20); - - if (file->type() == WiiFile::File) - { - int roundedSize = (file->length() + 63) & ~63; - atUint8* data = new atUint8[roundedSize]; - memset(data, 0, roundedSize); - - std::unique_ptr aes = NewAES(); - aes->setKey(SD_KEY); - aes->encrypt(iv, file->data(), data, roundedSize); - - writeBytes((atInt8*)data, roundedSize); - ret += roundedSize; - delete[] data; - } - - return ret; +void WiiSaveWriter::writeImage(WiiImage* image) { + atInt8* data = (atInt8*)image->data(); + writeBytes(data, image->width() * image->height() * 2); } +void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId) { + atUint8 sig[0x40]; + atUint8 ngCert[0x180]; + atUint8 apCert[0x180]; + atUint8* hash; + atUint8 apPriv[30]; + atUint8 apSig[60]; + char signer[64]; + char name[64]; + atUint8* buf; + atUint32 dataSize; -void WiiSaveWriter::writeImage(WiiImage* image) -{ - atInt8* data = (atInt8*)image->data(); - writeBytes(data, image->width() * image->height() * 2); + sprintf(signer, "Root-CA00000001-MS00000002"); + sprintf(name, "NG%08x", ngId); + ecc::makeECCert(ngCert, ngSig, signer, name, ngPriv, ngKeyId); + + memset(apPriv, 0, 30); + apPriv[10] = 1; + + memset(apSig, 81, 30); + + sprintf(signer, "Root-CA00000001-MS00000002-NG%08x", ngId); + sprintf(name, "AP%08x%08x", 1, 2); + ecc::makeECCert(apCert, apSig, signer, name, apPriv, 0); + + hash = getSha1(apCert + 0x80, 0x100); + ecc::createECDSA(apSig, apSig + 30, ngPriv, hash); + ecc::makeECCert(apCert, apSig, signer, name, apPriv, 0); + delete[] hash; + + dataSize = filesSize + 0x80; + buf = new atUint8[dataSize]; + atUint8* rawData = data(); + memcpy(buf, rawData + 0xF0C0, dataSize); + + hash = getSha1(buf, dataSize); + atUint8* hash2 = getSha1(hash, 20); + delete[] hash; + delete[] buf; + + ecc::createECDSA(sig, sig + 30, apPriv, hash2); + int stuff = 0x2f536969; + + if (!utility::isSystemBigEndian()) + stuff = utility::swap32(stuff); + + *(atUint32*)(sig + 60) = stuff; + delete[] hash2; + + writeBytes((atInt8*)sig, 0x40); + writeBytes((atInt8*)ngCert, 0x180); + writeBytes((atInt8*)apCert, 0x180); } -void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId) -{ - atUint8 sig[0x40]; - atUint8 ngCert[0x180]; - atUint8 apCert[0x180]; - atUint8* hash; - atUint8 apPriv[30]; - atUint8 apSig[60]; - char signer[64]; - char name[64]; - atUint8* buf; - atUint32 dataSize; - - sprintf(signer, "Root-CA00000001-MS00000002"); - sprintf(name, "NG%08x", ngId); - ecc::makeECCert(ngCert, ngSig, signer, name, ngPriv, ngKeyId); - - memset(apPriv, 0, 30); - apPriv[10] = 1; - - memset(apSig, 81, 30); - - sprintf(signer, "Root-CA00000001-MS00000002-NG%08x", ngId); - sprintf(name, "AP%08x%08x", 1, 2); - ecc::makeECCert(apCert, apSig, signer, name, apPriv, 0); - - hash = getSha1(apCert + 0x80, 0x100); - ecc::createECDSA(apSig, apSig + 30, ngPriv, hash); - ecc::makeECCert(apCert, apSig, signer, name, apPriv, 0); - delete[] hash; - - dataSize = filesSize + 0x80; - buf = new atUint8[dataSize]; - atUint8* rawData = data(); - memcpy(buf, rawData + 0xF0C0, dataSize); - - hash = getSha1(buf, dataSize); - atUint8* hash2 = getSha1(hash, 20); - delete[] hash; - delete[] buf; - - ecc::createECDSA(sig, sig + 30, apPriv, hash2); - int stuff = 0x2f536969; - - if (!utility::isSystemBigEndian()) - stuff = utility::swap32(stuff); - - *(atUint32*)(sig + 60) = stuff; - delete[] hash2; - - writeBytes((atInt8*)sig, 0x40); - writeBytes((atInt8*)ngCert, 0x180); - writeBytes((atInt8*)apCert, 0x180); -} - -} // io -} // zelda +} // namespace io +} // namespace athena diff --git a/src/athena/ZQuestFile.cpp b/src/athena/ZQuestFile.cpp index 805b1c5..de46271 100644 --- a/src/athena/ZQuestFile.cpp +++ b/src/athena/ZQuestFile.cpp @@ -2,31 +2,29 @@ #include -namespace athena -{ +namespace athena { std::vector GameStrings; -void initGameStrings() -{ - // Populate game strings - GameStrings.push_back("No Game"); - GameStrings.push_back("Legend Of Zelda"); - GameStrings.push_back("Adventure of Link"); - GameStrings.push_back("A Link to the Past"); - GameStrings.push_back("Links Awakening"); - GameStrings.push_back("Ocarina of Time"); - GameStrings.push_back("Ocarina of Time 3D"); - GameStrings.push_back("Majora's Mask"); - GameStrings.push_back("Oracle of Seasons"); - GameStrings.push_back("Oracle of Ages"); - GameStrings.push_back("For Swords"); - GameStrings.push_back("Wind Waker"); - GameStrings.push_back("Four Swords Adventures"); - GameStrings.push_back("Minish Cap"); - GameStrings.push_back("Twilight Princess"); - GameStrings.push_back("Phantom Hourglass"); - GameStrings.push_back("Spirit Tracks"); - GameStrings.push_back("Skyward Sword"); - GameStrings.push_back("A Link Between Worlds"); +void initGameStrings() { + // Populate game strings + GameStrings.push_back("No Game"); + GameStrings.push_back("Legend Of Zelda"); + GameStrings.push_back("Adventure of Link"); + GameStrings.push_back("A Link to the Past"); + GameStrings.push_back("Links Awakening"); + GameStrings.push_back("Ocarina of Time"); + GameStrings.push_back("Ocarina of Time 3D"); + GameStrings.push_back("Majora's Mask"); + GameStrings.push_back("Oracle of Seasons"); + GameStrings.push_back("Oracle of Ages"); + GameStrings.push_back("For Swords"); + GameStrings.push_back("Wind Waker"); + GameStrings.push_back("Four Swords Adventures"); + GameStrings.push_back("Minish Cap"); + GameStrings.push_back("Twilight Princess"); + GameStrings.push_back("Phantom Hourglass"); + GameStrings.push_back("Spirit Tracks"); + GameStrings.push_back("Skyward Sword"); + GameStrings.push_back("A Link Between Worlds"); } const atUint32 ZQuestFile::Major = 2; @@ -35,86 +33,51 @@ const atUint32 ZQuestFile::Revision = 0; const atUint32 ZQuestFile::Version = Major | (Minor << 8) | (Revision << 16); -const atUint32 ZQuestFile::Magic = 'Z' | ('Q' << 8) | ('S' << 16) | (('0' + ZQuestFile::Major) << 24); +const atUint32 ZQuestFile::Magic = 'Z' | ('Q' << 8) | ('S' << 16) | (('0' + ZQuestFile::Major) << 24); -ZQuestFile::ZQuestFile() - : m_game(NoGame), - m_endian(Endian::Little), - m_length(0) -{ - initGameStrings(); -} +ZQuestFile::ZQuestFile() : m_game(NoGame), m_endian(Endian::Little), m_length(0) { initGameStrings(); } -ZQuestFile::ZQuestFile(ZQuestFile::Game game, Endian endian, std::unique_ptr&& data, atUint32 length, const std::string& gameString) - : m_game(game), - m_gameString(gameString), - m_endian(endian), - m_data(std::move(data)), - m_length(length) -{ - initGameStrings(); - - if (gameString.empty() && (m_game < GameStrings.size() - 1)) - m_gameString = GameStrings[m_game]; -} - -void ZQuestFile::setGame(ZQuestFile::Game game) -{ - m_game = game; - - if (m_game > GameStrings.size() - 1) - return; +ZQuestFile::ZQuestFile(ZQuestFile::Game game, Endian endian, std::unique_ptr&& data, atUint32 length, + const std::string& gameString) +: m_game(game), m_gameString(gameString), m_endian(endian), m_data(std::move(data)), m_length(length) { + initGameStrings(); + if (gameString.empty() && (m_game < GameStrings.size() - 1)) m_gameString = GameStrings[m_game]; } -ZQuestFile::Game ZQuestFile::game() const -{ - return m_game; +void ZQuestFile::setGame(ZQuestFile::Game game) { + m_game = game; + + if (m_game > GameStrings.size() - 1) + return; + + m_gameString = GameStrings[m_game]; } -void ZQuestFile::setEndian(Endian endian) -{ - m_endian = endian; +ZQuestFile::Game ZQuestFile::game() const { return m_game; } + +void ZQuestFile::setEndian(Endian endian) { m_endian = endian; } + +Endian ZQuestFile::endian() const { return m_endian; } + +void ZQuestFile::setData(std::unique_ptr&& data, atUint32 length) { + m_data = std::move(data); + m_length = length; } -Endian ZQuestFile::endian() const -{ - return m_endian; -} +atUint8* ZQuestFile::data() const { return m_data.get(); } -void ZQuestFile::setData(std::unique_ptr&& data, atUint32 length) -{ - m_data = std::move(data); - m_length = length; -} +atUint32 ZQuestFile::length() const { return m_length; } -atUint8* ZQuestFile::data() const -{ - return m_data.get(); -} +void ZQuestFile::setGameString(const std::string& gameString) { m_gameString = gameString; } +std::string ZQuestFile::gameString() const { return m_gameString; } -atUint32 ZQuestFile::length() const -{ - return m_length; -} +const std::vector ZQuestFile::gameStringList() { + if (GameStrings.size() <= 0) + initGameStrings(); -void ZQuestFile::setGameString(const std::string& gameString) -{ - m_gameString = gameString; -} - -std::string ZQuestFile::gameString() const -{ - return m_gameString; -} - -const std::vector ZQuestFile::gameStringList() -{ - if (GameStrings.size() <= 0) - initGameStrings(); - - return GameStrings; -} + return GameStrings; } +} // namespace athena diff --git a/src/athena/ZQuestFileReader.cpp b/src/athena/ZQuestFileReader.cpp index 2b21ddf..479ff7d 100644 --- a/src/athena/ZQuestFileReader.cpp +++ b/src/athena/ZQuestFileReader.cpp @@ -7,102 +7,83 @@ #include #include -namespace athena::io -{ +namespace athena::io { -ZQuestFileReader::ZQuestFileReader(atUint8* data, atUint64 length) - : MemoryCopyReader(data, length) -{ +ZQuestFileReader::ZQuestFileReader(atUint8* data, atUint64 length) : MemoryCopyReader(data, length) {} + +ZQuestFileReader::ZQuestFileReader(const std::string& filename) : MemoryCopyReader(filename) {} + +ZQuestFile* ZQuestFileReader::read() { + atUint32 magic, version, compressedLen, uncompressedLen; + ZQuestFile::Game game = ZQuestFile::NoGame; + std::string gameString; + atUint16 BOM; + atUint32 checksum = 0; + + magic = readUint32(); + + if ((magic & 0x00FFFFFF) != (ZQuestFile::Magic & 0x00FFFFFF)) { + atError("Not a valid ZQuest file"); + return nullptr; + } + + version = readUint32(); + + if (version > ZQuestFile::Version) { + atError("Unsupported ZQuest version"); + return nullptr; + } + + compressedLen = readUint32(); + uncompressedLen = readUint32(); + + if (version >= ZQUEST_VERSION_CHECK(2, 0, 0)) { + gameString = std::string((const char*)readBytes(0x0A).get(), 0x0A); + + for (size_t i = 0; i < ZQuestFile::gameStringList().size(); i++) { + if (!ZQuestFile::gameStringList().at(i).substr(0, 0x0A).compare(gameString)) { + gameString = ZQuestFile::gameStringList().at(i); + game = (ZQuestFile::Game)i; + break; + } + } + + BOM = readUint16(); + checksum = readUint32(); + } else { + game = (ZQuestFile::Game)readUint32(); + BOM = readUint16(); + seek(0x0A); + } + + std::unique_ptr data = readUBytes(compressedLen); // compressedLen is always the total file size + + if (version >= ZQUEST_VERSION_CHECK(2, 0, 0)) { + if (checksum != athena::checksums::crc32(data.get(), compressedLen)) { + atError("Checksum mismatch, data corrupt"); + return nullptr; + } + } else { + std::clog << "ZQuest version 0x" << std::uppercase << std::setw(8) << std::setfill('0') << std::hex + << athena::utility::swapU32(version); + std::clog << " has no checksum field" << std::endl; + } + + if (compressedLen != uncompressedLen) { + atUint8* dst = new atUint8[uncompressedLen]; + atUint32 dstLen = io::Compression::decompressZlib(data.get(), compressedLen, dst, uncompressedLen); + + if (dstLen != uncompressedLen) { + delete[] dst; + atError("Error decompressing data"); + return nullptr; + } + + data.reset(dst); + } + + return new ZQuestFile(game, BOM == 0xFEFF ? Endian::Big : Endian::Little, std::move(data), uncompressedLen, + gameString); } -ZQuestFileReader::ZQuestFileReader(const std::string& filename) - : MemoryCopyReader(filename) -{ -} - -ZQuestFile* ZQuestFileReader::read() -{ - atUint32 magic, version, compressedLen, uncompressedLen; - ZQuestFile::Game game = ZQuestFile::NoGame; - std::string gameString; - atUint16 BOM; - atUint32 checksum = 0; - - magic = readUint32(); - - if ((magic & 0x00FFFFFF) != (ZQuestFile::Magic & 0x00FFFFFF)) - { - atError("Not a valid ZQuest file"); - return nullptr; - } - - version = readUint32(); - - if (version > ZQuestFile::Version) - { - atError("Unsupported ZQuest version"); - return nullptr; - } - - compressedLen = readUint32(); - uncompressedLen = readUint32(); - - if (version >= ZQUEST_VERSION_CHECK(2, 0, 0)) - { - gameString = std::string((const char*)readBytes(0x0A).get(), 0x0A); - - for (size_t i = 0; i < ZQuestFile::gameStringList().size(); i++) - { - if (!ZQuestFile::gameStringList().at(i).substr(0, 0x0A).compare(gameString)) - { - gameString = ZQuestFile::gameStringList().at(i); - game = (ZQuestFile::Game)i; - break; - } - } - - BOM = readUint16(); - checksum = readUint32(); - } - else - { - game = (ZQuestFile::Game)readUint32(); - BOM = readUint16(); - seek(0x0A); - } - - std::unique_ptr data = readUBytes(compressedLen); // compressedLen is always the total file size - - if (version >= ZQUEST_VERSION_CHECK(2, 0, 0)) - { - if (checksum != athena::checksums::crc32(data.get(), compressedLen)) - { - atError("Checksum mismatch, data corrupt"); - return nullptr; - } - } - else - { - std::clog << "ZQuest version 0x" << std::uppercase << std::setw(8) << std::setfill('0') << std::hex << athena::utility::swapU32(version); - std::clog << " has no checksum field" << std::endl; - } - - if (compressedLen != uncompressedLen) - { - atUint8* dst = new atUint8[uncompressedLen]; - atUint32 dstLen = io::Compression::decompressZlib(data.get(), compressedLen, dst, uncompressedLen); - - if (dstLen != uncompressedLen) - { - delete[] dst; - atError("Error decompressing data"); - return nullptr; - } - - data.reset(dst); - } - - return new ZQuestFile(game, BOM == 0xFEFF ? Endian::Big : Endian::Little, std::move(data), uncompressedLen, gameString); -} - -} // zelda +} // namespace athena::io diff --git a/src/athena/ZQuestFileWriter.cpp b/src/athena/ZQuestFileWriter.cpp index 89219c7..7a9dacc 100644 --- a/src/athena/ZQuestFileWriter.cpp +++ b/src/athena/ZQuestFileWriter.cpp @@ -3,74 +3,59 @@ #include "athena/Compression.hpp" #include "athena/Checksums.hpp" -namespace athena::io -{ +namespace athena::io { -ZQuestFileWriter::ZQuestFileWriter(atUint8* data, atUint64 length) - : MemoryCopyWriter(data, length) -{ -} +ZQuestFileWriter::ZQuestFileWriter(atUint8* data, atUint64 length) : MemoryCopyWriter(data, length) {} -ZQuestFileWriter::ZQuestFileWriter(const std::string& filename) - : MemoryCopyWriter(filename) -{ -} +ZQuestFileWriter::ZQuestFileWriter(const std::string& filename) : MemoryCopyWriter(filename) {} -void ZQuestFileWriter::write(ZQuestFile* quest, bool compress) -{ - if (!quest) - { - atError("quest cannot be NULL"); - return; +void ZQuestFileWriter::write(ZQuestFile* quest, bool compress) { + if (!quest) { + atError("quest cannot be NULL"); + return; + } + + writeUint32(ZQuestFile::Magic); + writeUint32(ZQuestFile::Version); + atUint8* questData = quest->data(); + atUint32 compLen; + + if (compress) { + atUint8* compData = + new atUint8[quest->length() + 0x40]; // add 20 bytes because sometimes the file grows with compression + compLen = quest->length() + 0x40; + compLen = io::Compression::compressZlib(questData, quest->length(), compData, compLen); + + // if the compressed data is the same length or larger than the original data, just store the original + if (compLen >= quest->length() || compLen <= 0) { + compLen = quest->length(); + // Delete the compressed data since we won't be using it + delete[] compData; + compData = NULL; + writeUint32(quest->length()); + } else { + // Don't do delete on data + questData = compData; + writeUint32(compLen); } - - writeUint32(ZQuestFile::Magic); - writeUint32(ZQuestFile::Version); - atUint8* questData = quest->data(); - atUint32 compLen; - - if (compress) - { - atUint8* compData = new atUint8[quest->length() + 0x40]; // add 20 bytes because sometimes the file grows with compression - compLen = quest->length() + 0x40; - compLen = io::Compression::compressZlib(questData, quest->length(), compData, compLen); - - // if the compressed data is the same length or larger than the original data, just store the original - if (compLen >= quest->length() || compLen <= 0) - { - compLen = quest->length(); - // Delete the compressed data since we won't be using it - delete[] compData; - compData = NULL; - writeUint32(quest->length()); - } - else - { - // Don't do delete on data - questData = compData; - writeUint32(compLen); - } - } - else - { - compLen = quest->length(); - writeUint32(quest->length()); - } - + } else { + compLen = quest->length(); writeUint32(quest->length()); - writeBytes((atInt8*)quest->gameString().substr(0, 0x0A).c_str(), 0x0A); - writeUint16(quest->endian() == Endian::Big ? 0xFFFE : 0xFEFF); - writeUint32(athena::checksums::crc32(questData, compLen)); - writeUBytes(questData, compLen); + } - save(); + writeUint32(quest->length()); + writeBytes((atInt8*)quest->gameString().substr(0, 0x0A).c_str(), 0x0A); + writeUint16(quest->endian() == Endian::Big ? 0xFFFE : 0xFEFF); + writeUint32(athena::checksums::crc32(questData, compLen)); + writeUBytes(questData, compLen); - // Delete compressed data to prevent memory leaks - if (questData != quest->data()) - { - delete[] questData; - questData = NULL; - } + save(); + + // Delete compressed data to prevent memory leaks + if (questData != quest->data()) { + delete[] questData; + questData = NULL; + } } -} // zelda +} // namespace athena::io diff --git a/src/bn.cpp b/src/bn.cpp index 37a9c89..a42590a 100644 --- a/src/bn.cpp +++ b/src/bn.cpp @@ -3,96 +3,82 @@ #include "bn.hpp" -namespace bignum -{ +namespace bignum { -void subModulus(atUint8* a, const atUint8* N, atUint32 n) -{ - atUint8 c = 0; +void subModulus(atUint8* a, const atUint8* N, atUint32 n) { + atUint8 c = 0; - for (atUint32 i = n - 1; i < n; i--) - { - atUint32 dig = N[i] + c; - c = (a[i] < dig); - a[i] -= dig; + for (atUint32 i = n - 1; i < n; i--) { + atUint32 dig = N[i] + c; + c = (a[i] < dig); + a[i] -= dig; + } +} + +void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n) { + atUint8 c = 0; + + for (atUint32 i = n - 1; i < n; i--) { + atUint32 dig = a[i] + b[i] + c; + c = (dig >= 0x100); + d[i] = dig; + } + + if (c) + subModulus(d, N, n); + + if (compare(d, N, n) >= 0) + subModulus(d, N, n); +} + +void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n) { + memset(d, 0, n); + + for (atUint32 i = 0; i < n; i++) { + for (atUint8 mask = 0x80; mask != 0; mask >>= 1) { + add(d, d, d, N, n); + + if ((a[i] & mask) != 0) + add(d, d, b, N, n); } + } } -void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n) -{ - atUint8 c = 0; +void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en) { + atUint8 t[512]; + memset(d, 0, n); + d[n - 1] = 1; - for (atUint32 i = n - 1; i < n; i--) - { - atUint32 dig = a[i] + b[i] + c; - c = (dig >= 0x100); - d[i] = dig; + for (atUint32 i = 0; i < en; i++) { + for (atUint8 mask = 0x80; mask != 0; mask >>= 1) { + mul(t, d, d, N, n); + + if ((e[i] & mask) != 0) + mul(d, t, a, N, n); + else + memcpy(d, t, n); } - - if (c) - subModulus(d, N, n); - - if (compare(d, N, n) >= 0) - subModulus(d, N, n); + } } -void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n) -{ - memset(d, 0, n); +void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n) { + atUint8 t[512], s[512]; - for (atUint32 i = 0; i < n; i++) - { - for (atUint8 mask = 0x80; mask != 0; mask >>= 1) - { - add(d, d, d, N, n); - - if ((a[i] & mask) != 0) - add(d, d, b, N, n); - } - } + memcpy(t, N, n); + memset(s, 0, n); + s[n - 1] = 2; + subModulus(t, s, n); + exp(d, a, N, n, t, n); } -void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en) -{ - atUint8 t[512]; - memset(d, 0, n); - d[n - 1] = 1; +int compare(const atUint8* a, const atUint8* b, atUint32 n) { + for (atUint32 i = 0; i < n; i++) { + if (a[i] < b[i]) + return -1; - for (atUint32 i = 0; i < en; i++) - { - for (atUint8 mask = 0x80; mask != 0; mask >>= 1) - { - mul(t, d, d, N, n); - - if ((e[i] & mask) != 0) - mul(d, t, a, N, n); - else - memcpy(d, t, n); - } - } -} - -void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n) -{ - atUint8 t[512], s[512]; - - memcpy(t, N, n); - memset(s, 0, n); - s[n - 1] = 2; - subModulus(t, s, n); - exp(d, a, N, n, t, n); -} - -int compare(const atUint8* a, const atUint8* b, atUint32 n) -{ - for (atUint32 i = 0; i < n; i++) - { - if (a[i] < b[i]) - return -1; - - if (a[i] > b[i]) - return 1; - } - return 0; -} + if (a[i] > b[i]) + return 1; + } + return 0; } +} // namespace bignum diff --git a/src/ec.cpp b/src/ec.cpp index 3ff4159..f28ad8f 100644 --- a/src/ec.cpp +++ b/src/ec.cpp @@ -5,219 +5,195 @@ #include "ec.hpp" #include "sha1.h" -namespace ecc -{ +namespace ecc { static int checkZero(const atUint8* d) { return !memcmp(d, d + 1, 29) && d[0] == 0; } -static void add(atUint8* d, const atUint8* a, const atUint8* b) -{ - for (atUint32 i = 0; i < 30; i++) - d[i] = a[i] ^ b[i]; +static void add(atUint8* d, const atUint8* a, const atUint8* b) { + for (atUint32 i = 0; i < 30; i++) + d[i] = a[i] ^ b[i]; } -static void multiply(atUint8* d, const atUint8* a, const atUint8* b) -{ - memset(d, 0, 30); - for (atUint32 n = 0, i = 0, mask = 1; n < 233; n++) - { - atUint8 x, y; - atUint8 carry = d[0] & 1; - x = 0; - for (atUint32 i = 0; i < 29; i++) - { - y = d[i + 1]; - d[i] = x ^ (y >> 7); - x = y << 1; - } - - d[29] = x ^ carry; - d[20] ^= carry << 2; - if ((a[i] & mask) != 0) - add(d, d, b); - - mask >>= 1; - if (mask == 0) - { - mask = 0x80; - i++; - } - } -} - -static void squareToWide(atUint8* d, const atUint8* a) -{ - static const atUint8 sq[16] = {0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, - 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55}; - for (atUint32 i = 0; i < 30; i++) - { - d[2 * i] = sq[a[i] >> 4]; - d[2 * i + 1] = sq[a[i] & 15]; - } -} - -static void wideReduce(atUint8* d) -{ - atUint32 i; - atUint8 x; - - for (i = 0; i < 30; i++) - { - x = d[i]; - - d[i + 19] ^= x >> 7; - d[i + 20] ^= x << 1; - d[i + 29] ^= x >> 1; - d[i + 30] ^= x << 7; +static void multiply(atUint8* d, const atUint8* a, const atUint8* b) { + memset(d, 0, 30); + for (atUint32 n = 0, i = 0, mask = 1; n < 233; n++) { + atUint8 x, y; + atUint8 carry = d[0] & 1; + x = 0; + for (atUint32 i = 0; i < 29; i++) { + y = d[i + 1]; + d[i] = x ^ (y >> 7); + x = y << 1; } - x = d[30] & ~1; - d[49] ^= x >> 7; - d[50] ^= x << 1; - d[59] ^= x >> 1; - d[30] &= 1; -} + d[29] = x ^ carry; + d[20] ^= carry << 2; + if ((a[i] & mask) != 0) + add(d, d, b); -static void square(atUint8* d, const atUint8* a) -{ - atUint8 wide[60]; - - squareToWide(wide, a); - wideReduce(wide); - - memcpy(d, wide + 30, 30); -} - -static void itInvert(atUint8* d, const atUint8* a, const atUint8* b, atUint32 j) -{ - atUint8 t[30]; - memcpy(t, a, 32); - while (j--) - { - square(d, t); - memcpy(t, d, 30); + mask >>= 1; + if (mask == 0) { + mask = 0x80; + i++; } - multiply(d, t, b); + } } -static void invert(atUint8* d, const atUint8* a) -{ - atUint8 t[30]; - atUint8 s[30]; - - itInvert(t, a, a, 1); - itInvert(s, t, a, 1); - itInvert(t, s, s, 3); - itInvert(s, t, a, 1); - itInvert(t, s, s, 7); - itInvert(s, t, t, 14); - itInvert(t, s, a, 1); - itInvert(s, t, t, 29); - itInvert(t, s, s, 58); - itInvert(s, t, t, 116); - square(d, s); +static void squareToWide(atUint8* d, const atUint8* a) { + static const atUint8 sq[16] = {0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, + 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55}; + for (atUint32 i = 0; i < 30; i++) { + d[2 * i] = sq[a[i] >> 4]; + d[2 * i + 1] = sq[a[i] & 15]; + } } -static void pointDouble(atUint8* r, const atUint8* p) -{ - atUint8 s[30], t[30]; - const atUint8* px = p; - const atUint8* py = p + 30; - atUint8* rx = r; - atUint8* ry = r + 30; +static void wideReduce(atUint8* d) { + atUint32 i; + atUint8 x; - if (checkZero(px)) - { - memset(rx, 0, 30); - memset(ry, 0, 30); + for (i = 0; i < 30; i++) { + x = d[i]; - return; - } + d[i + 19] ^= x >> 7; + d[i + 20] ^= x << 1; + d[i + 29] ^= x >> 1; + d[i + 30] ^= x << 7; + } - invert(t, px); - multiply(s, py, t); - add(s, s, px); - - square(t, px); - - square(rx, s); - add(rx, rx, s); - rx[29] ^= 1; - - multiply(ry, s, rx); - add(ry, ry, rx); - add(ry, ry, t); + x = d[30] & ~1; + d[49] ^= x >> 7; + d[50] ^= x << 1; + d[59] ^= x >> 1; + d[30] &= 1; } -static void pointAdd(atUint8* r, const atUint8* p, const atUint8* q) -{ - atUint8 s[30], t[30], u[30]; - const atUint8* px = p; - const atUint8* py = p + 30; - const atUint8* qx = q; - const atUint8* qy = q + 30; - atUint8* rx = r; - atUint8* ry = r + 30; +static void square(atUint8* d, const atUint8* a) { + atUint8 wide[60]; - if (checkZero(p) && checkZero(p + 30)) - { - memcpy(rx, qx, 30); - memcpy(ry, qy, 30); - return; - } + squareToWide(wide, a); + wideReduce(wide); - if (checkZero(p) && checkZero(p + 30)) - { - memcpy(rx, px, 30); - memcpy(ry, py, 30); - return; - } + memcpy(d, wide + 30, 30); +} - add(u, px, qx); +static void itInvert(atUint8* d, const atUint8* a, const atUint8* b, atUint32 j) { + atUint8 t[30]; + memcpy(t, a, 32); + while (j--) { + square(d, t); + memcpy(t, d, 30); + } + multiply(d, t, b); +} + +static void invert(atUint8* d, const atUint8* a) { + atUint8 t[30]; + atUint8 s[30]; + + itInvert(t, a, a, 1); + itInvert(s, t, a, 1); + itInvert(t, s, s, 3); + itInvert(s, t, a, 1); + itInvert(t, s, s, 7); + itInvert(s, t, t, 14); + itInvert(t, s, a, 1); + itInvert(s, t, t, 29); + itInvert(t, s, s, 58); + itInvert(s, t, t, 116); + square(d, s); +} + +static void pointDouble(atUint8* r, const atUint8* p) { + atUint8 s[30], t[30]; + const atUint8* px = p; + const atUint8* py = p + 30; + atUint8* rx = r; + atUint8* ry = r + 30; + + if (checkZero(px)) { + memset(rx, 0, 30); + memset(ry, 0, 30); + + return; + } + + invert(t, px); + multiply(s, py, t); + add(s, s, px); + + square(t, px); + + square(rx, s); + add(rx, rx, s); + rx[29] ^= 1; + + multiply(ry, s, rx); + add(ry, ry, rx); + add(ry, ry, t); +} + +static void pointAdd(atUint8* r, const atUint8* p, const atUint8* q) { + atUint8 s[30], t[30], u[30]; + const atUint8* px = p; + const atUint8* py = p + 30; + const atUint8* qx = q; + const atUint8* qy = q + 30; + atUint8* rx = r; + atUint8* ry = r + 30; + + if (checkZero(p) && checkZero(p + 30)) { + memcpy(rx, qx, 30); + memcpy(ry, qy, 30); + return; + } + + if (checkZero(p) && checkZero(p + 30)) { + memcpy(rx, px, 30); + memcpy(ry, py, 30); + return; + } + + add(u, px, qx); + + if (checkZero(u)) { + add(u, py, qy); if (checkZero(u)) - { - add(u, py, qy); - - if (checkZero(u)) - pointDouble(r, p); - else - { - memset(rx, 0, 30); - memset(ry, 0, 30); - } - - return; + pointDouble(r, p); + else { + memset(rx, 0, 30); + memset(ry, 0, 30); } - invert(t, u); - add(u, py, qy); - multiply(s, t, u); + return; + } - square(t, s); - add(t, t, s); - add(t, t, qx); - t[29] ^= 1; + invert(t, u); + add(u, py, qy); + multiply(s, t, u); - multiply(u, s, t); - add(s, u, py); - add(rx, t, px); - add(ry, s, rx); + square(t, s); + add(t, t, s); + add(t, t, qx); + t[29] ^= 1; + + multiply(u, s, t); + add(s, u, py); + add(rx, t, px); + add(ry, s, rx); } -static void pointMultiply(atUint8* d, const atUint8* a, const atUint8* b) -{ - memset(d, 0, 30); - memset(d + 30, 0, 30); - for (atUint32 i = 0; i < 30; i++) - { - for (atUint8 mask = 0x80; mask != 0; mask >>= 1) - { - pointDouble(d, d); +static void pointMultiply(atUint8* d, const atUint8* a, const atUint8* b) { + memset(d, 0, 30); + memset(d + 30, 0, 30); + for (atUint32 i = 0; i < 30; i++) { + for (atUint8 mask = 0x80; mask != 0; mask >>= 1) { + pointDouble(d, d); - if ((a[i] & mask) != 0) - pointAdd(d, d, b); - } + if ((a[i] & mask) != 0) + pointAdd(d, d, b); } + } } static const atUint8 ecG[60] = {0x00, 0xfa, 0xc9, 0xdf, 0xcb, 0xac, 0x83, 0x13, 0xbb, 0x21, 0x39, 0xf1, @@ -230,91 +206,87 @@ static const atUint8 ecN[30] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe9, 0x74, 0xe7, 0x2f, 0x8a, 0x69, 0x22, 0x03, 0x1d, 0x26, 0x03, 0xcf, 0xe0, 0xd7}; -bool checkECDSA(atUint8* Q, atUint8* R, atUint8* S, atUint8* hash) -{ - atUint8 Sinv[30]; - atUint8 e[30]; - atUint8 w1[30], w2[30]; - atUint8 r1[60], r2[60]; +bool checkECDSA(atUint8* Q, atUint8* R, atUint8* S, atUint8* hash) { + atUint8 Sinv[30]; + atUint8 e[30]; + atUint8 w1[30], w2[30]; + atUint8 r1[60], r2[60]; - bignum::inv(Sinv, S, ecN, 30); + bignum::inv(Sinv, S, ecN, 30); - memset(e, 0, 30); - memcpy(e + 10, hash, 20); + memset(e, 0, 30); + memcpy(e + 10, hash, 20); - bignum::mul(w1, e, Sinv, ecN, 30); - bignum::mul(w2, R, Sinv, ecN, 30); + bignum::mul(w1, e, Sinv, ecN, 30); + bignum::mul(w2, R, Sinv, ecN, 30); - pointMultiply(r1, w1, ecG); - pointMultiply(r2, w2, Q); + pointMultiply(r1, w1, ecG); + pointMultiply(r2, w2, Q); - pointAdd(r1, r1, r2); + pointAdd(r1, r1, r2); - if (bignum::compare(r1, ecN, 30) >= 0) - bignum::subModulus(r1, ecN, 30); + if (bignum::compare(r1, ecN, 30) >= 0) + bignum::subModulus(r1, ecN, 30); - return (bignum::compare(r1, R, 30) == 0); + return (bignum::compare(r1, R, 30) == 0); } -void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId) -{ - memset(cert, 0, 0x180); - *(atUint32*)(cert) = 0x10002; +void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId) { + memset(cert, 0, 0x180); + *(atUint32*)(cert) = 0x10002; - if (!athena::utility::isSystemBigEndian()) - *(atUint32*)(cert) = athena::utility::swapU32(*(atUint32*)(cert)); + if (!athena::utility::isSystemBigEndian()) + *(atUint32*)(cert) = athena::utility::swapU32(*(atUint32*)(cert)); - memcpy((char*)cert + 4, sig, 60); - strcpy((char*)cert + 0x80, signer); - *(atUint32*)(cert + 0xc0) = 2; + memcpy((char*)cert + 4, sig, 60); + strcpy((char*)cert + 0x80, signer); + *(atUint32*)(cert + 0xc0) = 2; - if (!athena::utility::isSystemBigEndian()) - *(atUint32*)(cert + 0xc0) = athena::utility::swapU32(*(atUint32*)(cert + 0xc0)); + if (!athena::utility::isSystemBigEndian()) + *(atUint32*)(cert + 0xc0) = athena::utility::swapU32(*(atUint32*)(cert + 0xc0)); - strcpy((char*)cert + 0xc4, name); - *(atUint32*)(cert + 0x104) = keyId; + strcpy((char*)cert + 0xc4, name); + *(atUint32*)(cert + 0x104) = keyId; - if (!athena::utility::isSystemBigEndian()) - *(atUint32*)(cert + 0x104) = athena::utility::swapU32(*(atUint32*)(cert + 0x104)); + if (!athena::utility::isSystemBigEndian()) + *(atUint32*)(cert + 0x104) = athena::utility::swapU32(*(atUint32*)(cert + 0x104)); - pointMultiply(cert + 0x108, priv, ecG); + pointMultiply(cert + 0x108, priv, ecG); } -void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash) -{ - atUint8 e[30]; - atUint8 kk[30]; - atUint8 m[30]; - atUint8 minv[30]; - atUint8 mG[60]; +void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash) { + atUint8 e[30]; + atUint8 kk[30]; + atUint8 m[30]; + atUint8 minv[30]; + atUint8 mG[60]; - memset(e, 0, 30); - memcpy(e + 10, hash, 20); + memset(e, 0, 30); + memcpy(e + 10, hash, 20); - athena::utility::fillRandom(m, sizeof(m)); - m[0] = 0; + athena::utility::fillRandom(m, sizeof(m)); + m[0] = 0; - pointMultiply(mG, m, ecG); - memcpy(R, mG, 30); + pointMultiply(mG, m, ecG); + memcpy(R, mG, 30); - if (bignum::compare(R, ecN, 30) >= 0) - bignum::subModulus(R, ecN, 30); + if (bignum::compare(R, ecN, 30) >= 0) + bignum::subModulus(R, ecN, 30); - memcpy(kk, k, 30); + memcpy(kk, k, 30); - if (bignum::compare(kk, ecN, 30) >= 0) - bignum::subModulus(kk, ecN, 30); + if (bignum::compare(kk, ecN, 30) >= 0) + bignum::subModulus(kk, ecN, 30); - bignum::mul(S, R, kk, ecN, 30); - bignum::add(kk, S, e, ecN, 30); - bignum::inv(minv, m, ecN, 30); - bignum::mul(S, minv, kk, ecN, 30); + bignum::mul(S, R, kk, ecN, 30); + bignum::add(kk, S, e, ecN, 30); + bignum::inv(minv, m, ecN, 30); + bignum::mul(S, minv, kk, ecN, 30); } -void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid) -{ - atUint8* apHash = getSha1(ap + 0x80, 0x100); - ngValid = checkECDSA(ng + 0x0108, ap + 0x04, ap + 0x22, apHash); - apValid = checkECDSA(ap + 0x0108, sig, sig + 30, sigHash); -} +void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid) { + atUint8* apHash = getSha1(ap + 0x80, 0x100); + ngValid = checkECDSA(ng + 0x0108, ap + 0x04, ap + 0x22, apHash); + apValid = checkECDSA(ap + 0x0108, sig, sig + 30, sigHash); } +} // namespace ecc diff --git a/src/md5.cpp b/src/md5.cpp index 0277181..3f5caf8 100644 --- a/src/md5.cpp +++ b/src/md5.cpp @@ -92,8 +92,7 @@ #include "md5.h" -namespace MD5Hash -{ +namespace MD5Hash { /* -------------------------------------------------------------------------- ** * Static Constants: * @@ -117,43 +116,36 @@ namespace MD5Hash * array. They're divided up into four groups of 16. */ -static const uint8_t K[3][16] = -{ +static const uint8_t K[3][16] = { /* Round 1: skipped (since it is simply sequential). */ - { 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 }, /* R2 */ - { 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 }, /* R3 */ - { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 } /* R4 */ + {1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12}, /* R2 */ + {5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2}, /* R3 */ + {0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9} /* R4 */ }; -static const uint8_t S[4][4] = { { 7, 12, 17, 22 }, /* Round 1 */ - { 5, 9, 14, 20 }, /* Round 2 */ - { 4, 11, 16, 23 }, /* Round 3 */ - { 6, 10, 15, 21 } /* Round 4 */ +static const uint8_t S[4][4] = { + {7, 12, 17, 22}, /* Round 1 */ + {5, 9, 14, 20}, /* Round 2 */ + {4, 11, 16, 23}, /* Round 3 */ + {6, 10, 15, 21} /* Round 4 */ }; -static const uint32_t T[4][16] = { { - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */ - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, - 0xa679438e, 0x49b40821 - }, +static const uint32_t T[4][16] = { + {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */ + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, + 0xfd987193, 0xa679438e, 0x49b40821}, - { - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */ - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, - 0x676f02d9, 0x8d2a4c8a - }, + {0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */ + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, + 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a}, - { - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* Round 3 */ - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, - 0x1fa27cf8, 0xc4ac5665 - }, + {0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* Round 3 */ + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, + 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665}, - { - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* Round 4 */ - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, - 0x2ad7d2bb, 0xeb86d391 - }, + {0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* Round 4 */ + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, + 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}, }; /* -------------------------------------------------------------------------- ** @@ -168,14 +160,14 @@ static const uint32_t T[4][16] = { { * */ -#define md5F( X, Y, Z ) ( ((X) & (Y)) | ((~(X)) & (Z)) ) -#define md5G( X, Y, Z ) ( ((X) & (Z)) | ((Y) & (~(Z))) ) -#define md5H( X, Y, Z ) ( (X) ^ (Y) ^ (Z) ) -#define md5I( X, Y, Z ) ( (Y) ^ ((X) | (~(Z))) ) +#define md5F(X, Y, Z) (((X) & (Y)) | ((~(X)) & (Z))) +#define md5G(X, Y, Z) (((X) & (Z)) | ((Y) & (~(Z)))) +#define md5H(X, Y, Z) ((X) ^ (Y) ^ (Z)) +#define md5I(X, Y, Z) ((Y) ^ ((X) | (~(Z)))) -#define GetLongByte( L, idx ) ((unsigned char)(( L >> (((idx) & 0x03) << 3) ) & 0xFF)) +#define GetLongByte(L, idx) ((unsigned char)((L >> (((idx)&0x03) << 3)) & 0xFF)) -#define STR2HEX(x) ((x >= 0x30) && (x <= 0x39)) ? x - 0x30 : toupper((int)x)-0x37 +#define STR2HEX(x) ((x >= 0x30) && (x <= 0x39)) ? x - 0x30 : toupper((int)x) - 0x37 /* -------------------------------------------------------------------------- ** * Static Functions: @@ -215,91 +207,87 @@ static void Permute(uint32_t ABCD[4], const unsigned char block[64]) * ------------------------------------------------------------------------ ** */ { - int round; - int i, j; - uint8_t s; - uint32_t a, b, c, d; - uint32_t KeepABCD[4]; - uint32_t X[16]; + int round; + int i, j; + uint8_t s; + uint32_t a, b, c, d; + uint32_t KeepABCD[4]; + uint32_t X[16]; - /* Store the current ABCD values for later re-use. - */ - for (i = 0; i < 4; i++) - KeepABCD[i] = ABCD[i]; + /* Store the current ABCD values for later re-use. + */ + for (i = 0; i < 4; i++) + KeepABCD[i] = ABCD[i]; - /* Convert the input block into an array of unsigned longs, taking care - * to read the block in Little Endian order (the algorithm assumes this). - * The uint32_t values are then handled in host order. - */ - for (i = 0, j = 0; i < 16; i++) - { - X[i] = (uint32_t) block[j++]; - X[i] |= ((uint32_t) block[j++] << 8); - X[i] |= ((uint32_t) block[j++] << 16); - X[i] |= ((uint32_t) block[j++] << 24); + /* Convert the input block into an array of unsigned longs, taking care + * to read the block in Little Endian order (the algorithm assumes this). + * The uint32_t values are then handled in host order. + */ + for (i = 0, j = 0; i < 16; i++) { + X[i] = (uint32_t)block[j++]; + X[i] |= ((uint32_t)block[j++] << 8); + X[i] |= ((uint32_t)block[j++] << 16); + X[i] |= ((uint32_t)block[j++] << 24); + } + + /* This loop performs the four rounds of permutations. + * The rounds are each very similar. The differences are in three areas: + * - The function (F, G, H, or I) used to perform bitwise permutations + * on the registers, + * - The order in which values from X[] are chosen. + * - Changes to the number of bits by which the registers are rotated. + * This implementation uses a switch statement to deal with some of the + * differences between rounds. Other differences are handled by storing + * values in arrays and using the round number to select the correct set + * of values. + * + * (My implementation appears to be a poor compromise between speed, size, + * and clarity. Ugh. [crh]) + */ + for (round = 0; round < 4; round++) { + for (i = 0; i < 16; i++) { + j = (4 - (i % 4)) & 0x3; /* handles the rotation of ABCD. */ + s = S[round][i % 4]; /* is the bit shift for this iteration. */ + + b = ABCD[(j + 1) & 0x3]; /* Copy the b,c,d values per ABCD rotation. */ + c = ABCD[(j + 2) & 0x3]; /* This isn't really necessary, it just looks */ + d = ABCD[(j + 3) & 0x3]; /* clean & will hopefully be optimized away. */ + + /* The actual perumation function. + * This is broken out to minimize the code within the switch(). + */ + switch (round) { + case 0: + /* round 1 */ + a = md5F(b, c, d) + X[i]; + break; + + case 1: + /* round 2 */ + a = md5G(b, c, d) + X[K[0][i]]; + break; + + case 2: + /* round 3 */ + a = md5H(b, c, d) + X[K[1][i]]; + break; + + default: + /* round 4 */ + a = md5I(b, c, d) + X[K[2][i]]; + break; + } + + a = 0xFFFFFFFF & (ABCD[j] + a + T[round][i]); + ABCD[j] = b + (0xFFFFFFFF & ((a << s) | (a >> (32 - s)))); } + } - /* This loop performs the four rounds of permutations. - * The rounds are each very similar. The differences are in three areas: - * - The function (F, G, H, or I) used to perform bitwise permutations - * on the registers, - * - The order in which values from X[] are chosen. - * - Changes to the number of bits by which the registers are rotated. - * This implementation uses a switch statement to deal with some of the - * differences between rounds. Other differences are handled by storing - * values in arrays and using the round number to select the correct set - * of values. - * - * (My implementation appears to be a poor compromise between speed, size, - * and clarity. Ugh. [crh]) - */ - for (round = 0; round < 4; round++) - { - for (i = 0; i < 16; i++) - { - j = (4 - (i % 4)) & 0x3; /* handles the rotation of ABCD. */ - s = S[round][i % 4]; /* is the bit shift for this iteration. */ - - b = ABCD[(j + 1) & 0x3]; /* Copy the b,c,d values per ABCD rotation. */ - c = ABCD[(j + 2) & 0x3]; /* This isn't really necessary, it just looks */ - d = ABCD[(j + 3) & 0x3]; /* clean & will hopefully be optimized away. */ - - /* The actual perumation function. - * This is broken out to minimize the code within the switch(). - */ - switch (round) - { - case 0: - /* round 1 */ - a = md5F(b, c, d) + X[i]; - break; - - case 1: - /* round 2 */ - a = md5G(b, c, d) + X[K[0][i]]; - break; - - case 2: - /* round 3 */ - a = md5H(b, c, d) + X[K[1][i]]; - break; - - default: - /* round 4 */ - a = md5I(b, c, d) + X[K[2][i]]; - break; - } - - a = 0xFFFFFFFF & (ABCD[j] + a + T[round][i]); - ABCD[j] = b + (0xFFFFFFFF & ((a << s) | (a >> (32 - s)))); - } - } - - /* Use the stored original A, B, C, D values to perform - * one last convolution. - */ - for (i = 0; i < 4; i++) - ABCD[i] = 0xFFFFFFFF & (ABCD[i] + KeepABCD[i]); + /* Use the stored original A, B, C, D values to perform + * one last convolution. + */ + for (i = 0; i < 4; i++) + ABCD[i] = 0xFFFFFFFF & (ABCD[i] + KeepABCD[i]); } /* Permute */ @@ -336,22 +324,22 @@ auth_md5Ctx* auth_md5InitCtx(auth_md5Ctx* ctx) * ------------------------------------------------------------------------ ** */ { - ctx->len = 0; - ctx->b_used = 0; + ctx->len = 0; + ctx->b_used = 0; - ctx->ABCD[0] = 0x67452301; /* The array ABCD[] contains the four 4-byte */ - ctx->ABCD[1] = 0xefcdab89; /* "registers" that are manipulated to */ - ctx->ABCD[2] = 0x98badcfe; /* produce the MD5 digest. The input acts */ - ctx->ABCD[3] = 0x10325476; /* upon the registers, not the other way */ - /* 'round. The initial values are those */ - /* given in RFC 1321 (pg. 4). Note, however, that RFC 1321 */ - /* provides these values as bytes, not as longwords, and the */ - /* bytes are arranged in little-endian order as if they were */ - /* the bytes of (little endian) 32-bit ints. That's */ - /* confusing as all getout (to me, anyway). The values given */ - /* here are provided as 32-bit values in C language format, */ - /* so they are endian-agnostic. */ - return (ctx); + ctx->ABCD[0] = 0x67452301; /* The array ABCD[] contains the four 4-byte */ + ctx->ABCD[1] = 0xefcdab89; /* "registers" that are manipulated to */ + ctx->ABCD[2] = 0x98badcfe; /* produce the MD5 digest. The input acts */ + ctx->ABCD[3] = 0x10325476; /* upon the registers, not the other way */ + /* 'round. The initial values are those */ + /* given in RFC 1321 (pg. 4). Note, however, that RFC 1321 */ + /* provides these values as bytes, not as longwords, and the */ + /* bytes are arranged in little-endian order as if they were */ + /* the bytes of (little endian) 32-bit ints. That's */ + /* confusing as all getout (to me, anyway). The values given */ + /* here are provided as 32-bit values in C language format, */ + /* so they are endian-agnostic. */ + return (ctx); } /* auth_md5InitCtx */ auth_md5Ctx* auth_md5SumCtx(auth_md5Ctx* ctx, const unsigned char* src, const int len) @@ -371,30 +359,28 @@ auth_md5Ctx* auth_md5SumCtx(auth_md5Ctx* ctx, const unsigned char* src, const in * ------------------------------------------------------------------------ ** */ { - int i; + int i; - /* Add the new block's length to the total length. - */ - ctx->len += (uint32_t) len; + /* Add the new block's length to the total length. + */ + ctx->len += (uint32_t)len; - /* Copy the new block's data into the context block. - * Call the Permute() function whenever the context block is full. - */ - for (i = 0; i < len; i++) - { - ctx->block[ctx->b_used] = src[i]; - (ctx->b_used)++; + /* Copy the new block's data into the context block. + * Call the Permute() function whenever the context block is full. + */ + for (i = 0; i < len; i++) { + ctx->block[ctx->b_used] = src[i]; + (ctx->b_used)++; - if (64 == ctx->b_used) - { - Permute(ctx->ABCD, ctx->block); - ctx->b_used = 0; - } + if (64 == ctx->b_used) { + Permute(ctx->ABCD, ctx->block); + ctx->b_used = 0; } + } - /* Return the updated context. - */ - return (ctx); + /* Return the updated context. + */ + return (ctx); } /* auth_md5SumCtx */ auth_md5Ctx* auth_md5CloseCtx(auth_md5Ctx* ctx, unsigned char* dst) @@ -417,60 +403,58 @@ auth_md5Ctx* auth_md5CloseCtx(auth_md5Ctx* ctx, unsigned char* dst) * ------------------------------------------------------------------------ ** */ { - int i; - uint32_t l; + int i; + uint32_t l; - /* Add the required 0x80 padding initiator byte. - * The auth_md5SumCtx() function always permutes and resets the context - * block when it gets full, so we know that there must be at least one - * free byte in the context block. - */ - ctx->block[ctx->b_used] = 0x80; - (ctx->b_used)++; + /* Add the required 0x80 padding initiator byte. + * The auth_md5SumCtx() function always permutes and resets the context + * block when it gets full, so we know that there must be at least one + * free byte in the context block. + */ + ctx->block[ctx->b_used] = 0x80; + (ctx->b_used)++; - /* Zero out any remaining free bytes in the context block. - */ - for (i = ctx->b_used; i < 64; i++) - ctx->block[i] = 0; + /* Zero out any remaining free bytes in the context block. + */ + for (i = ctx->b_used; i < 64; i++) + ctx->block[i] = 0; - /* We need 8 bytes to store the length field. - * If we don't have 8, call Permute() and reset the context block. - */ - if (56 < ctx->b_used) - { - Permute(ctx->ABCD, ctx->block); - - for (i = 0; i < 64; i++) - ctx->block[i] = 0; - } - - /* Add the total length and perform the final perumation. - * Note: The 60'th byte is read from the *original* len> value - * and shifted to the correct position. This neatly avoids - * any MAXINT numeric overflow issues. - */ - l = ctx->len << 3; - - for (i = 0; i < 4; i++) - ctx->block[56 + i] |= GetLongByte(l, i); - - ctx->block[60] = ((GetLongByte(ctx->len, 3) & 0xE0) >> 5); /* See Above! */ + /* We need 8 bytes to store the length field. + * If we don't have 8, call Permute() and reset the context block. + */ + if (56 < ctx->b_used) { Permute(ctx->ABCD, ctx->block); - /* Now copy the result into the output buffer and we're done. - */ - for (i = 0; i < 4; i++) - { - dst[0 + i] = GetLongByte(ctx->ABCD[0], i); - dst[4 + i] = GetLongByte(ctx->ABCD[1], i); - dst[8 + i] = GetLongByte(ctx->ABCD[2], i); - dst[12 + i] = GetLongByte(ctx->ABCD[3], i); - } + for (i = 0; i < 64; i++) + ctx->block[i] = 0; + } - /* Return the context. - * This is done for compatibility with the other auth_md5*Ctx() functions. - */ - return (ctx); + /* Add the total length and perform the final perumation. + * Note: The 60'th byte is read from the *original* len> value + * and shifted to the correct position. This neatly avoids + * any MAXINT numeric overflow issues. + */ + l = ctx->len << 3; + + for (i = 0; i < 4; i++) + ctx->block[56 + i] |= GetLongByte(l, i); + + ctx->block[60] = ((GetLongByte(ctx->len, 3) & 0xE0) >> 5); /* See Above! */ + Permute(ctx->ABCD, ctx->block); + + /* Now copy the result into the output buffer and we're done. + */ + for (i = 0; i < 4; i++) { + dst[0 + i] = GetLongByte(ctx->ABCD[0], i); + dst[4 + i] = GetLongByte(ctx->ABCD[1], i); + dst[8 + i] = GetLongByte(ctx->ABCD[2], i); + dst[12 + i] = GetLongByte(ctx->ABCD[3], i); + } + + /* Return the context. + * This is done for compatibility with the other auth_md5*Ctx() functions. + */ + return (ctx); } /* auth_md5CloseCtx */ unsigned char* MD5(unsigned char* dst, const unsigned char* src, const int len) @@ -507,13 +491,13 @@ unsigned char* MD5(unsigned char* dst, const unsigned char* src, const int len) * ------------------------------------------------------------------------ ** */ { - auth_md5Ctx ctx[1]; + auth_md5Ctx ctx[1]; - (void) auth_md5InitCtx(ctx); /* Open a context. */ - (void) auth_md5SumCtx(ctx, src, len); /* Pass only one block. */ - (void) auth_md5CloseCtx(ctx, dst); /* Close the context. */ + (void)auth_md5InitCtx(ctx); /* Open a context. */ + (void)auth_md5SumCtx(ctx, src, len); /* Pass only one block. */ + (void)auth_md5CloseCtx(ctx, dst); /* Close the context. */ - return (dst); /* Makes life easy. */ + return (dst); /* Makes life easy. */ } /* auth_md5Sum */ unsigned char* MD5fromFile(unsigned char* dst, const char* src) @@ -548,90 +532,83 @@ unsigned char* MD5fromFile(unsigned char* dst, const char* src) * ------------------------------------------------------------------------ ** */ { - auth_md5Ctx ctx[1]; + auth_md5Ctx ctx[1]; - FILE* file; - unsigned int blksize = 0; - unsigned int read = 0; - unsigned int filesize; - unsigned char* buffer; + FILE* file; + unsigned int blksize = 0; + unsigned int read = 0; + unsigned int filesize; + unsigned char* buffer; - file = fopen(src, "rb"); + file = fopen(src, "rb"); - if (file == NULL) - { - return NULL; - } + if (file == NULL) { + return NULL; + } - (void) auth_md5InitCtx(ctx); /* Open a context. */ + (void)auth_md5InitCtx(ctx); /* Open a context. */ - fseek(file, 0, SEEK_END); - filesize = ftell(file); - rewind(file); + fseek(file, 0, SEEK_END); + filesize = ftell(file); + rewind(file); - if (filesize < 1048576) //1MB cache for files bigger than 1 MB - blksize = filesize; - else blksize = 1048576; + if (filesize < 1048576) // 1MB cache for files bigger than 1 MB + blksize = filesize; + else + blksize = 1048576; - buffer = (unsigned char*)malloc(blksize); - - if (buffer == NULL) - { - //no memory - fclose(file); - return NULL; - } - - do - { - read = (int)fread(buffer, 1, blksize, file); - (void) auth_md5SumCtx(ctx, buffer, read); /* Pass only one block. */ - - } - while (read > 0); + buffer = (unsigned char*)malloc(blksize); + if (buffer == NULL) { + // no memory fclose(file); - free(buffer); + return NULL; + } - (void) auth_md5CloseCtx(ctx, dst); /* Close the context. */ + do { + read = (int)fread(buffer, 1, blksize, file); + (void)auth_md5SumCtx(ctx, buffer, read); /* Pass only one block. */ - return (dst); /* Makes life easy. */ + } while (read > 0); + + fclose(file); + free(buffer); + + (void)auth_md5CloseCtx(ctx, dst); /* Close the context. */ + + return (dst); /* Makes life easy. */ } /* auth_md5Sum */ -const char* MD5ToString(const unsigned char* hash, char* dst) -{ - char hexchar[3]; - short i = 0, n = 0; +const char* MD5ToString(const unsigned char* hash, char* dst) { + char hexchar[3]; + short i = 0, n = 0; - for (i = 0; i < 16; i++) - { - sprintf(hexchar, "%02X", hash[i]); + for (i = 0; i < 16; i++) { + sprintf(hexchar, "%02X", hash[i]); - dst[n++] = hexchar[0]; - dst[n++] = hexchar[1]; - } + dst[n++] = hexchar[0]; + dst[n++] = hexchar[1]; + } - dst[n] = 0x00; + dst[n] = 0x00; - return dst; + return dst; } -unsigned char* StringToMD5(const char* hash, unsigned char* dst) -{ - char hexchar[2]; - short i = 0, n = 0; +unsigned char* StringToMD5(const char* hash, unsigned char* dst) { + char hexchar[2]; + short i = 0, n = 0; - for (i = 0; i < 16; i++) - { - hexchar[0] = hash[n++]; - hexchar[1] = hash[n++]; + for (i = 0; i < 16; i++) { + hexchar[0] = hash[n++]; + hexchar[1] = hash[n++]; - dst[i] = STR2HEX(hexchar[0]); - dst[i] <<= 4; - dst[i] += STR2HEX(hexchar[1]); - } + dst[i] = STR2HEX(hexchar[0]); + dst[i] <<= 4; + dst[i] += STR2HEX(hexchar[1]); + } - return dst; + return dst; } -} // MD5Hash +} // namespace MD5Hash /* ========================================================================== */ diff --git a/src/sha1.cpp b/src/sha1.cpp index 050d779..1ccca56 100644 --- a/src/sha1.cpp +++ b/src/sha1.cpp @@ -45,9 +45,7 @@ /* * Define the circular shift macro */ -#define SHA1CircularShift(bits,word) \ - ((((word) << (bits)) & 0xFFFFFFFF) | \ - ((word) >> (32-(bits)))) +#define SHA1CircularShift(bits, word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32 - (bits)))) /* Function prototypes */ void SHA1ProcessMessageBlock(SHA1Context*); @@ -70,20 +68,19 @@ void SHA1PadMessage(SHA1Context*); * Comments: * */ -void SHA1Reset(SHA1Context* context) -{ - context->Length_Low = 0; - context->Length_High = 0; - context->Message_Block_Index = 0; +void SHA1Reset(SHA1Context* context) { + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; - context->Message_Digest[0] = 0x67452301; - context->Message_Digest[1] = 0xEFCDAB89; - context->Message_Digest[2] = 0x98BADCFE; - context->Message_Digest[3] = 0x10325476; - context->Message_Digest[4] = 0xC3D2E1F0; + context->Message_Digest[0] = 0x67452301; + context->Message_Digest[1] = 0xEFCDAB89; + context->Message_Digest[2] = 0x98BADCFE; + context->Message_Digest[3] = 0x10325476; + context->Message_Digest[4] = 0xC3D2E1F0; - context->Computed = 0; - context->Corrupted = 0; + context->Computed = 0; + context->Corrupted = 0; } /* @@ -103,21 +100,18 @@ void SHA1Reset(SHA1Context* context) * Comments: * */ -int SHA1Result(SHA1Context* context) -{ +int SHA1Result(SHA1Context* context) { - if (context->Corrupted) - { - return 0; - } + if (context->Corrupted) { + return 0; + } - if (!context->Computed) - { - SHA1PadMessage(context); - context->Computed = 1; - } + if (!context->Computed) { + SHA1PadMessage(context); + context->Computed = 1; + } - return 1; + return 1; } /* @@ -142,50 +136,40 @@ int SHA1Result(SHA1Context* context) * Comments: * */ -void SHA1Input(SHA1Context* context, - const unsigned char* message_array, - unsigned length) -{ - if (!length) - { - return; - } +void SHA1Input(SHA1Context* context, const unsigned char* message_array, unsigned length) { + if (!length) { + return; + } - if (context->Computed || context->Corrupted) - { + if (context->Computed || context->Corrupted) { + context->Corrupted = 1; + return; + } + + while (length-- && !context->Corrupted) { + context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF); + + context->Length_Low += 8; + /* Force it to 32 bits */ + context->Length_Low &= 0xFFFFFFFF; + + if (context->Length_Low == 0) { + context->Length_High++; + /* Force it to 32 bits */ + context->Length_High &= 0xFFFFFFFF; + + if (context->Length_High == 0) { + /* Message is too long */ context->Corrupted = 1; - return; + } } - while (length-- && !context->Corrupted) - { - context->Message_Block[context->Message_Block_Index++] = - (*message_array & 0xFF); - - context->Length_Low += 8; - /* Force it to 32 bits */ - context->Length_Low &= 0xFFFFFFFF; - - if (context->Length_Low == 0) - { - context->Length_High++; - /* Force it to 32 bits */ - context->Length_High &= 0xFFFFFFFF; - - if (context->Length_High == 0) - { - /* Message is too long */ - context->Corrupted = 1; - } - } - - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); - } - - message_array++; + if (context->Message_Block_Index == 64) { + SHA1ProcessMessageBlock(context); } + + message_array++; + } } /* @@ -208,100 +192,81 @@ void SHA1Input(SHA1Context* context, * * */ -void SHA1ProcessMessageBlock(SHA1Context* context) -{ - const unsigned K[] = /* Constants defined in SHA-1 */ - { - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; /* Loop counter */ - unsigned temp; /* Temporary word value */ - unsigned W[80]; /* Word sequence */ - unsigned A, B, C, D, E; /* Word buffers */ +void SHA1ProcessMessageBlock(SHA1Context* context) { + const unsigned K[] = /* Constants defined in SHA-1 */ + {0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6}; + int t; /* Loop counter */ + unsigned temp; /* Temporary word value */ + unsigned W[80]; /* Word sequence */ + unsigned A, B, C, D, E; /* Word buffers */ - /* - * Initialize the first 16 words in the array W - */ - for (t = 0; t < 16; t++) - { - W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; - W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; - W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; - W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); - } + /* + * Initialize the first 16 words in the array W + */ + for (t = 0; t < 16; t++) { + W[t] = ((unsigned)context->Message_Block[t * 4]) << 24; + W[t] |= ((unsigned)context->Message_Block[t * 4 + 1]) << 16; + W[t] |= ((unsigned)context->Message_Block[t * 4 + 2]) << 8; + W[t] |= ((unsigned)context->Message_Block[t * 4 + 3]); + } - for (t = 16; t < 80; t++) - { - W[t] = SHA1CircularShift(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); - } + for (t = 16; t < 80; t++) { + W[t] = SHA1CircularShift(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); + } - A = context->Message_Digest[0]; - B = context->Message_Digest[1]; - C = context->Message_Digest[2]; - D = context->Message_Digest[3]; - E = context->Message_Digest[4]; + A = context->Message_Digest[0]; + B = context->Message_Digest[1]; + C = context->Message_Digest[2]; + D = context->Message_Digest[3]; + E = context->Message_Digest[4]; - for (t = 0; t < 20; t++) - { - temp = SHA1CircularShift(5, A) + - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30, B); - B = A; - A = temp; - } + for (t = 0; t < 20; t++) { + temp = SHA1CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } - for (t = 20; t < 40; t++) - { - temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30, B); - B = A; - A = temp; - } + for (t = 20; t < 40; t++) { + temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } - for (t = 40; t < 60; t++) - { - temp = SHA1CircularShift(5, A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30, B); - B = A; - A = temp; - } + for (t = 40; t < 60; t++) { + temp = SHA1CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } - for (t = 60; t < 80; t++) - { - temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3]; - temp &= 0xFFFFFFFF; - E = D; - D = C; - C = SHA1CircularShift(30, B); - B = A; - A = temp; - } + for (t = 60; t < 80; t++) { + temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } - context->Message_Digest[0] = - (context->Message_Digest[0] + A) & 0xFFFFFFFF; - context->Message_Digest[1] = - (context->Message_Digest[1] + B) & 0xFFFFFFFF; - context->Message_Digest[2] = - (context->Message_Digest[2] + C) & 0xFFFFFFFF; - context->Message_Digest[3] = - (context->Message_Digest[3] + D) & 0xFFFFFFFF; - context->Message_Digest[4] = - (context->Message_Digest[4] + E) & 0xFFFFFFFF; + context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF; + context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF; + context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF; + context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF; + context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF; - context->Message_Block_Index = 0; + context->Message_Block_Index = 0; } /* @@ -327,76 +292,67 @@ void SHA1ProcessMessageBlock(SHA1Context* context) * Comments: * */ -void SHA1PadMessage(SHA1Context* context) -{ - /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second - * block. - */ - if (context->Message_Block_Index > 55) - { - context->Message_Block[context->Message_Block_Index++] = 0x80; +void SHA1PadMessage(SHA1Context* context) { + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) { + context->Message_Block[context->Message_Block_Index++] = 0x80; - while (context->Message_Block_Index < 64) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - - SHA1ProcessMessageBlock(context); - - while (context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } + while (context->Message_Block_Index < 64) { + context->Message_Block[context->Message_Block_Index++] = 0; } - else - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - - while (context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - - /* - * Store the message length as the last 8 octets - */ - context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; - context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; - context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; - context->Message_Block[59] = (context->Length_High) & 0xFF; - context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; - context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; - context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; - context->Message_Block[63] = (context->Length_Low) & 0xFF; SHA1ProcessMessageBlock(context); -} -atUint8* getSha1(atUint8* stuff, atUint32 stuff_size) -{ - SHA1Context sha; - SHA1Reset(&sha); - SHA1Input(&sha, (const atUint8*)stuff, stuff_size); - - if (!SHA1Result(&sha)) - return 0; - - atUint8* ret = new atUint8[20]; - memset(ret, 0, 20); - - for (int i = 0; i < 5 ; i++) - { - int val = sha.Message_Digest[ i ]; - - if (!athena::utility::isSystemBigEndian()) - val = athena::utility::swap32(val); - - memmove((char*)ret + (i * 4), &val, 4); + while (context->Message_Block_Index < 56) { + context->Message_Block[context->Message_Block_Index++] = 0; } + } else { + context->Message_Block[context->Message_Block_Index++] = 0x80; - return ret; + while (context->Message_Block_Index < 56) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; + context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; + context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; + context->Message_Block[59] = (context->Length_High) & 0xFF; + context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; + context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; + context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; + context->Message_Block[63] = (context->Length_Low) & 0xFF; + + SHA1ProcessMessageBlock(context); +} + +atUint8* getSha1(atUint8* stuff, atUint32 stuff_size) { + SHA1Context sha; + SHA1Reset(&sha); + SHA1Input(&sha, (const atUint8*)stuff, stuff_size); + + if (!SHA1Result(&sha)) + return 0; + + atUint8* ret = new atUint8[20]; + memset(ret, 0, 20); + + for (int i = 0; i < 5; i++) { + int val = sha.Message_Digest[i]; + + if (!athena::utility::isSystemBigEndian()) + val = athena::utility::swap32(val); + + memmove((char*)ret + (i * 4), &val, 4); + } + + return ret; }