diff --git a/.travis.yml b/.travis.yml index d46ae3a..e0a7b6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,17 @@ compiler: - - gcc-4.8 + - clang before_install: + - sudo add-apt-repository --yes "deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.6 main" + - wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -; - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test - sudo apt-get update -qq - - sudo apt-get install -qq g++-4.8 - - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8 - - sudo update-alternatives --config gcc + - sudo apt-get install -qq qt5-default clang-3.6 libclang-3.6-dev script: - - qmake Athena.pro + - qmake QMAKE_CXX=clang++-3.6 QMAKE_CC=clang-3.6 Athena.pro + - make + - cd atdna + - qmake QMAKE_CXX=clang++-3.6 QMAKE_CC=clang-3.6 QMAKE_LINK=clang++-3.6 LLVM_CONFIG=llvm-config-3.6 atdna.pro - make - -notifications: - irc: "irc.wiiking2.com#wiiking2" diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index f3e203f..9c9ba8e 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,7 +1,7 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.31.gd6a4897 +pkgver=1.1.0.32.g1aa3a70 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') diff --git a/atdna/atdna.pro b/atdna/atdna.pro index e6b7a11..58bb3d6 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -7,7 +7,13 @@ DEFINES += __STDC_LIMIT_MACROS=1 __STDC_CONSTANT_MACROS=1 QMAKE_CXXFLAGS += -fno-rtti QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter +isEmpty(LLVM_CONFIG) { + LLVM_CONFIG = llvm-config +} + INCLUDEPATH += ../include +INCLUDEPATH += $$system($$LLVM_CONFIG --includedir) +LIBS += -L$$system($$LLVM_CONFIG --libdir) CONFIG(debug, debug|release) { # FOR FULL DEBUGGING, PLEASE UNCOMMENT THESE AND POINT THEM TO diff --git a/atdna/main.cpp b/atdna/main.cpp index 5aad7cc..f6e9cee 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -1,3 +1,4 @@ +#include #include "clang/AST/ASTConsumer.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" @@ -35,6 +36,9 @@ static llvm::cl::list IncludeSearchPaths("I", llvm::cl::desc("Header search path"), llvm::cl::Prefix); +static unsigned AthenaError = 0; +#define ATHENA_DNA_BASETYPE "struct Athena::io::DNA" + class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { clang::ASTContext& context; @@ -106,7 +110,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor } } for (const clang::CXXBaseSpecifier& base : rDecl->bases()) - if (!base.getType().getCanonicalType().getAsString().compare(0, 22, "struct Athena::io::DNA")) + if (!base.getType().getCanonicalType().getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE)-1, ATHENA_DNA_BASETYPE)) { isDNAType = true; return "write(writer);"; @@ -174,7 +178,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor } } for (const clang::CXXBaseSpecifier& base : rDecl->bases()) - if (!base.getType().getCanonicalType().getAsString().compare(0, 22, "struct Athena::io::DNA")) + if (!base.getType().getCanonicalType().getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE)-1, ATHENA_DNA_BASETYPE)) { isDNAType = true; return "read(reader);"; @@ -202,7 +206,7 @@ public: for (const clang::CXXBaseSpecifier& base : decl->bases()) { clang::QualType canonType = base.getType().getCanonicalType(); - if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) + if (!canonType.getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE)-1, ATHENA_DNA_BASETYPE)) { foundDNA = true; break; @@ -211,12 +215,13 @@ public: if (!foundDNA) return true; + /* Two passes - read then write */ for (int p=0 ; p<2 ; ++p) { if (p) - fileOut << "void " << decl->getQualifiedNameAsString() << "::write(Athena::IStreamWriter& writer) const\n{\n"; + fileOut << "void " << decl->getQualifiedNameAsString() << "::write(Athena::io::IStreamWriter& writer) const\n{\n"; else - fileOut << "void " << decl->getQualifiedNameAsString() << "::read(Athena::IStreamReader& reader)\n{\n"; + fileOut << "void " << decl->getQualifiedNameAsString() << "::read(Athena::io::IStreamReader& reader)\n{\n"; int currentEndian = -1; for (const clang::FieldDecl* field : decl->fields()) @@ -227,205 +232,644 @@ public: if (regType->getTypeClass() == clang::Type::Elaborated) regType = regType->getUnqualifiedDesugaredType(); - if (regType->getTypeClass() == clang::Type::TemplateSpecialization) + /* Resolve constant array */ + size_t arraySize = 1; + bool isArray = false; + if (regType->getTypeClass() == clang::Type::ConstantArray) { - const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; - const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); - const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); + isArray = true; + const clang::ConstantArrayType* caType = (clang::ConstantArrayType*)regType; + arraySize = caType->getSize().getZExtValue(); + qualType = caType->getElementType(); + regTypeInfo = context.getTypeInfo(qualType); + regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::Elaborated) + regType = regType->getUnqualifiedDesugaredType(); + } - if (!tsDecl->getNameAsString().compare("Value")) + for (int e=0 ; esize() >= 2) - { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - const clang::Expr* defArg = nttParm->getDefaultArgument(); - llvm::APSInt result; - if (defArg->isIntegerConstantExpr(result, context)) - endian = result.getSExtValue(); - } - } - - clang::QualType templateType; - std::string ioOp; - bool isDNAType = false; - const clang::TemplateArgument* typeArg = nullptr; - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Type) - { - typeArg = &arg; - templateType = arg.getAsType().getCanonicalType(); - const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); - std::string fieldName = field->getName().str(); - ioOp = GetOpString(type, regTypeInfo.Width, fieldName, p, isDNAType); - } - else if (arg.getKind() == clang::TemplateArgument::Expression) - { - llvm::APSInt value; - if (arg.getAsExpr()->isIntegerConstantExpr(value, context)) - endian = value.getSExtValue(); - } - } - - if (ioOp.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error: %0")); - diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - return false; - } - - if (currentEndian != endian) - { - if (endian == 0) - fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); - else if (endian == 1) - fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); - currentEndian = endian; - } - - fileOut << " /* " << field->getName() << " */\n"; - if (!p) - fileOut << " " << field->getName() << " = " << ioOp << ";\n"; - else - fileOut << " " << ioOp << "\n"; + char subscript[16]; + snprintf(subscript, 16, "[%d]", e); + fieldName = field->getNameAsString() + subscript; } - else if (!tsDecl->getNameAsString().compare("Vector")) - { - int endian = -1; - if (classParms->size() >= 3) - { - const clang::NamedDecl* endianParm = classParms->getParam(2); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; - const clang::Expr* defArg = nttParm->getDefaultArgument(); - llvm::APSInt result; - if (defArg->isIntegerConstantExpr(result, context)) - endian = result.getSExtValue(); - } - } + else + fieldName = field->getNameAsString(); - clang::QualType templateType; - const clang::DeclRefExpr* cntRefExpr = nullptr; - std::string ioOp; - bool isDNAType = false; - std::string sizeVar; - const clang::TemplateArgument* typeArg = nullptr; - const clang::TemplateArgument* sizeArg = nullptr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) + 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->getNameAsString().compare("Value")) { - if (arg.getKind() == clang::TemplateArgument::Type) + llvm::APSInt endian(64, -1); + const clang::Expr* endianExpr = nullptr; + if (classParms->size() >= 2) { - typeArg = &arg; - templateType = arg.getAsType().getCanonicalType(); - clang::TypeInfo typeInfo = context.getTypeInfo(templateType); - static const std::string itStr = "*it"; - ioOp = GetOpString(templateType.getTypePtr(), typeInfo.Width, itStr, p, isDNAType); - } - else if (arg.getKind() == clang::TemplateArgument::Expression) - { - const clang::Expr* expr = arg.getAsExpr(); - if (idx == 1) + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - sizeArg = &arg; - const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + endianExpr = defArg; + if (!defArg->isIntegerConstantExpr(endian, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true)); + continue; + } + } + } + + clang::QualType templateType; + std::string ioOp; + bool isDNAType = false; + const clang::TemplateArgument* typeArg = nullptr; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + templateType = arg.getAsType().getCanonicalType(); + const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); + ioOp = GetOpString(type, regTypeInfo.Width, fieldName, p, isDNAType); + } + else if (arg.getKind() == clang::TemplateArgument::Expression) + { + const clang::Expr* expr = arg.getAsExpr(); + endianExpr = expr; + if (expr->isIntegerConstantExpr(endian, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); + continue; + } + } + } + + int endianVal = endian.getSExtValue(); + if (endianVal != 0 && endianVal != 1) + { + if (endianExpr) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true)); + } + else + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + continue; + } + + if (ioOp.empty()) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + continue; + } + + if (currentEndian != endianVal) + { + if (endianVal == 0) + fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); + else if (endianVal == 1) + fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); + currentEndian = endianVal; + } + + fileOut << " /* " << fieldName << " */\n"; + if (!p) + fileOut << " " << fieldName << " = " << ioOp << ";\n"; + else + fileOut << " " << ioOp << "\n"; + } + else if (!tsDecl->getNameAsString().compare("Vector")) + { + llvm::APSInt endian(64, -1); + const clang::Expr* endianExpr = nullptr; + if (classParms->size() >= 3) + { + const clang::NamedDecl* endianParm = classParms->getParam(2); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) + { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + endianExpr = defArg; + if (!defArg->isIntegerConstantExpr(endian, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true)); + continue; + } + } + } + + clang::QualType templateType; + std::string ioOp; + bool isDNAType = false; + std::string sizeExpr; + const clang::TemplateArgument* typeArg = nullptr; + const clang::TemplateArgument* sizeArg = nullptr; + size_t idx = 0; + bool bad = false; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + templateType = arg.getAsType().getCanonicalType(); + clang::TypeInfo typeInfo = context.getTypeInfo(templateType); + static const std::string elemStr = "elem"; + ioOp = GetOpString(templateType.getTypePtr(), typeInfo.Width, elemStr, p, isDNAType); + } + else if (arg.getKind() == clang::TemplateArgument::Expression) + { + const clang::Expr* expr = arg.getAsExpr(); + if (idx == 1) + { + sizeArg = &arg; + 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 strStream(sizeExpr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + } + else if (idx == 2) + { + endianExpr = expr; + if (!expr->isIntegerConstantExpr(endian, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); + bad = true; + break; + } + } + } + ++idx; + } + if (bad) + continue; + + int endianVal = endian.getSExtValue(); + if (endianVal != 0 && endianVal != 1) + { + if (endianExpr) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true)); + } + else + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + continue; + } + + 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; + } + + if (currentEndian != endianVal) + { + if (endianVal == 0) + fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); + else if (endianVal == 1) + fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); + currentEndian = endianVal; + } + + fileOut << " /* " << fieldName << " */\n"; + if (!p) + { + fileOut << " " << fieldName << ".clear();\n"; + fileOut << " " << fieldName << ".reserve(" << sizeExpr << ");\n"; + if (isDNAType) + fileOut << " for (int i=0 ; i<(" << sizeExpr << ") ; ++i)\n" + " {\n" + " " << fieldName << ".emplace_back();\n" + " " << fieldName << ".back()." << ioOp << "\n" + " }\n"; + else + fileOut << " for (int i=0 ; i<(" << sizeExpr << ") ; ++i)\n " << fieldName << ".push_back(" << ioOp << ");\n"; + } + else + { + fileOut << " for (auto elem : " << fieldName << ")\n"; + if (isDNAType) + fileOut << " elem." << ioOp << "\n"; + else + fileOut << " " << ioOp << "\n"; + } + + } + else if (!tsDecl->getNameAsString().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(); 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) + 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; + } + + fileOut << " /* " << fieldName << " */\n"; + if (!p) + { + fileOut << " " << fieldName << ".reset(new atUint8[" << sizeExprStr << "]);\n"; + fileOut << " reader.readUBytesToBuf(" << fieldName << ".get(), " << sizeExprStr << ");\n"; + } + else + { + fileOut << " writer.writeUBytes(" << fieldName << ".get(), " << sizeExprStr << ");\n"; + } + } + else if (!tsDecl->getNameAsString().compare("String")) + { + const clang::Expr* sizeExpr = nullptr; + std::string sizeExprStr; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Expression) + { + const clang::Expr* expr = arg.getAsExpr(); + 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(); + sizeExpr = argExpr; + llvm::raw_string_ostream strStream(sizeExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + else if (expr->isIntegerConstantExpr(sizeLiteral, context)) + { + sizeExprStr = sizeLiteral.toString(10); + } + } + } + + fileOut << " /* " << fieldName << " */\n"; + if (!p) + fileOut << " " << fieldName << " = reader.readString(" << sizeExprStr << ");\n"; + else + fileOut << " writer.writeString(" << fieldName << ");\n"; + } + else if (!tsDecl->getNameAsString().compare("WString")) + { + llvm::APSInt endian(64, -1); + const clang::Expr* endianExpr = nullptr; + if (classParms->size() >= 2) + { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) + { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + endianExpr = defArg; + if (!defArg->isIntegerConstantExpr(endian, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(defArg->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(defArg->getSourceRange(), true)); + continue; + } + } + } + + const clang::Expr* sizeExpr = nullptr; + std::string sizeExprStr; + size_t idx = 0; + bool bad = false; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Expression) + { + const clang::Expr* expr = arg.getAsExpr(); + if (idx == 0) + { + llvm::APSInt sizeLiteral; + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) { - cntRefExpr = (clang::DeclRefExpr*)argExpr; - sizeVar = cntRefExpr->getFoundDecl()->getNameAsString(); + 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()); + } + else if (expr->isIntegerConstantExpr(sizeLiteral, context)) + { + sizeExprStr = sizeLiteral.toString(10); + } + } + else if (idx == 1) + { + endianExpr = expr; + if (!expr->isIntegerConstantExpr(endian, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); + bad = true; + break; } } } - else if (idx == 2) + ++idx; + } + if (bad) + continue; + + int endianVal = endian.getSExtValue(); + if (endianVal != 0 && endianVal != 1) + { + if (endianExpr) { - llvm::APSInt value; - if (expr->isIntegerConstantExpr(value, context)) - endian = value.getSExtValue(); + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(endianExpr->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(endianExpr->getSourceRange(), true)); + } + else + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), AthenaError); + diag.AddString("Endian value must be 'BigEndian' or 'LittleEndian'"); + diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); + } + continue; + } + + if (currentEndian != endianVal) + { + if (endianVal == 0) + fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); + else if (endianVal == 1) + fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); + currentEndian = endianVal; + } + + fileOut << " /* " << fieldName << " */\n"; + if (!p) + fileOut << " " << fieldName << " = reader.readWString(" << sizeExprStr << ");\n"; + else + fileOut << " writer.writeWString(" << fieldName << ");\n"; + } + else if (!tsDecl->getNameAsString().compare("UTF8")) + { + const clang::Expr* sizeExpr = nullptr; + std::string sizeExprStr; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Expression) + { + const clang::Expr* expr = arg.getAsExpr(); + 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(); + sizeExpr = argExpr; + llvm::raw_string_ostream strStream(sizeExprStr); + argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); + } + else if (expr->isIntegerConstantExpr(sizeLiteral, context)) + { + sizeExprStr = sizeLiteral.toString(10); + } } } - ++idx; - } - if (ioOp.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error: %0")); - diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - return false; - } - - if (sizeVar.empty()) - { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocStart(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error: %0")); - diag.AddString("Unable to use count variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - return false; - } - - if (currentEndian != endian) - { - if (endian == 0) - fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); - else if (endian == 1) - fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); - currentEndian = endian; - } - - fileOut << " /* " << field->getName() << " */\n"; - if (!p) - { - fileOut << " " << field->getName() << ".clear();\n"; - fileOut << " " << field->getName() << ".reserve(" << sizeVar << ");\n"; - if (isDNAType) - fileOut << " for (int i=0 ; i<" << sizeVar << " ; ++i)\n" - " {\n" - " " << field->getName() << ".emplace_back();\n" - " " << field->getName() << ".back()." << ioOp << "\n" - " }\n"; + fileOut << " /* " << fieldName << " */\n"; + if (!p) + fileOut << " " << fieldName << " = reader.readUnicode(" << sizeExprStr << ");\n"; else - fileOut << " for (int i=0 ; i<" << sizeVar << " ; ++i)\n " << field->getName() << ".push_back(" << ioOp << ");\n"; + fileOut << " writer.writeUnicode(" << fieldName << ");\n"; } - else + else if (!tsDecl->getNameAsString().compare("Seek")) { - if (isDNAType) - fileOut << " for (int i=0, auto it=" << field->getName() << ".begin() ; i<" << sizeVar << " && it!=" << field->getName() << ".end() ; ++i, ++it)\n it->" << ioOp << "\n"; - else - fileOut << " for (int i=0, auto it=" << field->getName() << ".begin() ; i<" << sizeVar << " && it!=" << field->getName() << ".end() ; ++i, ++it)\n " << ioOp << "\n"; + size_t idx = 0; + llvm::APSInt offset(64, 0); + 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(); + if (!idx) + { + if (!expr->isIntegerConstantExpr(offset, context)) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getLocStart(), AthenaError); + diag.AddString("Unable to use non-constant offset expression in Athena"); + diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); + bad = true; + break; + } + } + 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 offsetVal = offset.getSExtValue(); + 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; + } + + fileOut << " /* " << fieldName << " */\n"; + if (directionVal == 0) + { + if (!p) + fileOut << " reader.seek(" << offsetVal << ", Athena::Begin);\n"; + else + fileOut << " writer.seek(" << offsetVal << ", Athena::Begin);\n"; + } + else if (directionVal == 1) + { + if (!p) + fileOut << " reader.seek(" << offsetVal << ", Athena::Current);\n"; + else + fileOut << " writer.seek(" << offsetVal << ", Athena::Current);\n"; + } + else if (directionVal == 2) + { + if (!p) + fileOut << " reader.seek(" << offsetVal << ", Athena::End);\n"; + else + fileOut << " writer.seek(" << offsetVal << ", Athena::End);\n"; + } + + } + else if (!tsDecl->getNameAsString().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) + { + fileOut << " /* " << fieldName << " */\n"; + if (alignVal == 32) + { + if (!p) + fileOut << " reader.seekAlign32();\n"; + else + fileOut << " writer.seekAlign32();\n"; + } + else if (align.isPowerOf2()) + { + if (!p) + fileOut << " reader.seek((reader.position() + " << alignVal-1 << ") & ~" << alignVal-1 << ", SeekOrigin::Begin);\n"; + else + fileOut << " writer.seek((writer.position() + " << alignVal-1 << ") & ~" << alignVal-1 << ", SeekOrigin::Begin);\n"; + } + else + { + if (!p) + fileOut << " reader.seek((reader.position() + " << alignVal-1 << ") / " << alignVal << " * " << alignVal << ", SeekOrigin::Begin);\n"; + else + fileOut << " writer.seek((writer.position() + " << alignVal-1 << ") / " << alignVal << " * " << alignVal << ", SeekOrigin::Begin);\n"; + } + } } } - } - - else if (regType->getTypeClass() == clang::Type::Record) - { - const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - if (cxxRDecl) + else if (regType->getTypeClass() == clang::Type::Record) { - for (const clang::CXXBaseSpecifier& base : cxxRDecl->bases()) + const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); + if (cxxRDecl) { - clang::QualType canonType = base.getType().getCanonicalType(); - if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) + for (const clang::CXXBaseSpecifier& base : cxxRDecl->bases()) { - fileOut << " /* " << field->getName() << " */\n"; - fileOut << " " << field->getName() << (p ? ".write(writer);\n" : ".read(reader);\n"); - currentEndian = -1; - break; + clang::QualType canonType = base.getType().getCanonicalType(); + if (!canonType.getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE)-1, ATHENA_DNA_BASETYPE)) + { + fileOut << " /* " << fieldName << " */\n"; + fileOut << " " << fieldName << (p ? ".write(writer);\n" : ".read(reader);\n"); + currentEndian = -1; + break; + } } } } + } } @@ -457,7 +901,7 @@ public: fileOut << "#include \"" << inputf << "\"\n"; fileOut << "\n"; - /* Second pass - emit file */ + /* Emit file */ emitVisitor.TraverseDecl(context.getTranslationUnitDecl()); } }; @@ -474,6 +918,7 @@ public: fileout = compiler.createOutputFile(OutputFilename, false, true, "", "", true); else fileout = compiler.createDefaultOutputFile(false, "a", "cpp"); + AthenaError = compiler.getASTContext().getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Athena error: %0"); return std::unique_ptr(new ATDNAConsumer(compiler.getASTContext(), *fileout)); } }; diff --git a/atdna/test.hpp b/atdna/test.hpp index aaa01a0..6df4abd 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -27,10 +27,21 @@ struct ANCSFile : public io::DNA ANCSSubFile subFile; - Value arrCount; - Vector array; + Align<4> align; + + Value arrCount[2]; + Vector array; + + Seek<21, Current> seek; Value arrCount2; - Vector array2; + Vector array2; + + Value bufSz; + Buffer buf; + + String<32> str; + WString<64> wstr; + UTF8<> utf8str[5]; }; diff --git a/include/Athena/Checksums.hpp b/include/Athena/Checksums.hpp index b1583a0..4f6cc42 100644 --- a/include/Athena/Checksums.hpp +++ b/include/Athena/Checksums.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef CHECKSUMS_HPP #define CHECKSUMS_HPP diff --git a/include/Athena/Compression.hpp b/include/Athena/Compression.hpp index aba7602..a2caa4a 100644 --- a/include/Athena/Compression.hpp +++ b/include/Athena/Compression.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef COMPRESSION_HPP #define COMPRESSION_HPP diff --git a/include/Athena/DNA.hpp b/include/Athena/DNA.hpp index f04da86..1a62c89 100644 --- a/include/Athena/DNA.hpp +++ b/include/Athena/DNA.hpp @@ -11,6 +11,7 @@ #include "IStreamReader.hpp" #include "IStreamWriter.hpp" #include +#include namespace Athena { @@ -34,6 +35,24 @@ struct DNA template using Vector = std::vector; + template + using Buffer = std::unique_ptr; + + template + using String = std::string; + + template + using WString = std::wstring; + + template + using UTF8 = std::string; + + template + struct Seek {}; + + template + struct Align {}; + virtual void read(IStreamReader&)=0; virtual void write(IStreamWriter&) const=0; }; diff --git a/include/Athena/Exception.hpp b/include/Athena/Exception.hpp index f3f719e..385388f 100644 --- a/include/Athena/Exception.hpp +++ b/include/Athena/Exception.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef EXCEPTION_HPP #define EXCEPTION_HPP diff --git a/include/Athena/FileNotFoundException.hpp b/include/Athena/FileNotFoundException.hpp index 9f52936..f09ef64 100644 --- a/include/Athena/FileNotFoundException.hpp +++ b/include/Athena/FileNotFoundException.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef FILENOTFOUNDEXCEPTION_HPP #define FILENOTFOUNDEXCEPTION_HPP diff --git a/include/Athena/FileReader.hpp b/include/Athena/FileReader.hpp index fccdd27..ce4a0a8 100644 --- a/include/Athena/FileReader.hpp +++ b/include/Athena/FileReader.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef FILESTREAM_HPP #define FILESTREAM_HPP @@ -63,7 +48,10 @@ public: double readDouble(); float readFloat(); bool readBool(); + atVec3f readVec3f(); + atVec4f readVec4f(); std::string readString(atInt32 maxlen = -1); + std::wstring readWString(atInt32 maxLen = -1); std::string readUnicode(atInt32 maxlen = -1); protected: std::string m_filename; diff --git a/include/Athena/FileWriter.hpp b/include/Athena/FileWriter.hpp index ba0c11a..3afcaaa 100644 --- a/include/Athena/FileWriter.hpp +++ b/include/Athena/FileWriter.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef FILEWRITER_HPP #define FILEWRITER_HPP @@ -57,7 +42,10 @@ public: void writeDouble(double val); void writeFloat(float val); void writeBool(bool val); + void writeVec3f(atVec3f vec); + void writeVec4f(atVec4f vec); void writeString(const std::string& val); + void writeWString(const std::wstring& str); void writeUnicode(const std::string& str); void fill(atInt8 byte, atUint64 len); void fill(atUint8 byte, atUint64 len); diff --git a/include/Athena/Global.hpp b/include/Athena/Global.hpp index c9b6d16..4ac92c1 100644 --- a/include/Athena/Global.hpp +++ b/include/Athena/Global.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef GLOBAL_HPP #define GLOBAL_HPP diff --git a/include/Athena/IOException.hpp b/include/Athena/IOException.hpp index 5046bc5..1e8d396 100644 --- a/include/Athena/IOException.hpp +++ b/include/Athena/IOException.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef IOEXCEPTION_HPP #define IOEXCEPTION_HPP diff --git a/include/Athena/IStream.hpp b/include/Athena/IStream.hpp index 99a9e84..b4c29b6 100644 --- a/include/Athena/IStream.hpp +++ b/include/Athena/IStream.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef STREAM_HPP #define STREAM_HPP diff --git a/include/Athena/IStreamReader.hpp b/include/Athena/IStreamReader.hpp index 4124136..6c3cfc6 100644 --- a/include/Athena/IStreamReader.hpp +++ b/include/Athena/IStreamReader.hpp @@ -38,8 +38,11 @@ public: virtual double readDouble() = 0; virtual float readFloat() = 0; virtual bool readBool() = 0; + virtual atVec3f readVec3f() = 0; + virtual atVec4f readVec4f() = 0; virtual std::string readUnicode(atInt32 = -1) = 0; virtual std::string readString(atInt32 = -1) = 0; + virtual std::wstring readWString(atInt32 = -1) = 0; }; } } diff --git a/include/Athena/IStreamWriter.hpp b/include/Athena/IStreamWriter.hpp index 1f72f3e..df7e4a2 100644 --- a/include/Athena/IStreamWriter.hpp +++ b/include/Athena/IStreamWriter.hpp @@ -36,7 +36,10 @@ public: virtual void writeDouble(double) = 0; virtual void writeFloat(float) = 0; virtual void writeBool(bool) = 0; + virtual void writeVec3f(atVec3f vec) = 0; + virtual void writeVec4f(atVec4f vec) = 0; virtual void writeString(const std::string&) = 0; + virtual void writeWString(const std::wstring&) = 0; virtual void writeUnicode(const std::string&) = 0; virtual void fill(atUint8, atUint64) = 0; virtual void fill(atInt8, atUint64) = 0; diff --git a/include/Athena/InvalidDataException.hpp b/include/Athena/InvalidDataException.hpp index e781cfb..2444fbc 100644 --- a/include/Athena/InvalidDataException.hpp +++ b/include/Athena/InvalidDataException.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef INVALIDDATAEXCEPTION_HPP #define INVALIDDATAEXCEPTION_HPP diff --git a/include/Athena/InvalidOperationException.hpp b/include/Athena/InvalidOperationException.hpp index 28487a9..fd6210d 100644 --- a/include/Athena/InvalidOperationException.hpp +++ b/include/Athena/InvalidOperationException.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef INVALID_OPERATION_EXCEPTION_HPP #define INVALID_OPERATION_EXCEPTION_HPP diff --git a/include/Athena/MemoryReader.hpp b/include/Athena/MemoryReader.hpp index b4cec76..9206baf 100644 --- a/include/Athena/MemoryReader.hpp +++ b/include/Athena/MemoryReader.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef MEMORYREADER_HPP #define MEMORYREADER_HPP @@ -268,6 +253,20 @@ public: */ bool readBool(); + /*! \brief Reads an atVec3f (12 bytes) and advances the current position + * + * \return atVec3f The value at the current address + * \throw IOException when address is out of range + */ + atVec3f readVec3f(); + + /*! \brief Reads an atVec4f (16 bytes) and advances the current position + * + * \return atVec4f The value at the current address + * \throw IOException when address is out of range + */ + atVec4f readVec4f(); + /*! \brief Reads a Unicode string and advances the position in the file * * \return std::string The value at the current address @@ -282,6 +281,13 @@ public: */ std::string readString(atInt32 maxlen = -1); + /*! \brief Reads a wstring and advances the position in the file + * + * \return std::wstring The value at the current address + * \throw IOException when address is out of range + */ + std::wstring readWString(atInt32 maxlen = -1); + void setProgressCallback(std::function cb); protected: void loadData(); diff --git a/include/Athena/MemoryWriter.hpp b/include/Athena/MemoryWriter.hpp index 5042da5..53247f4 100644 --- a/include/Athena/MemoryWriter.hpp +++ b/include/Athena/MemoryWriter.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef MEMORYWRITER_HPP #define MEMORYWRITER_HPP @@ -261,6 +246,22 @@ public: */ void writeBool(bool); + /*! \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. + * + * \sa Endian + * \param vec The value to write to the buffer + */ + void writeVec3f(atVec3f vec); + + /*! \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. + * + * \sa Endian + * \param vec The value to write to the buffer + */ + void writeVec4f(atVec4f vec); + /*! \brief Writes an unicode string to the buffer and advances the buffer. * It also swaps the bytes depending on the platform and Stream settings. * @@ -276,6 +277,14 @@ public: */ void writeString(const std::string& str); + /*! \brief Writes an wstring to the buffer and advances the buffer. + * + * \sa Endian + * \param str The string to write to the buffer + */ + void writeWString(const std::wstring& str); + + void fill(atUint8 val, atUint64 length); void fill(atInt8 val, atUint64 length); diff --git a/include/Athena/NotImplementedException.hpp b/include/Athena/NotImplementedException.hpp index 4419724..dd93703 100644 --- a/include/Athena/NotImplementedException.hpp +++ b/include/Athena/NotImplementedException.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef NOTIMPLEMENTEDEXCEPTION_HPP #define NOTIMPLEMENTEDEXCEPTION_HPP diff --git a/include/Athena/Types.hpp b/include/Athena/Types.hpp index 53445df..765e19a 100644 --- a/include/Athena/Types.hpp +++ b/include/Athena/Types.hpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #ifndef TYPES_HPP #define TYPES_HPP #include diff --git a/include/Athena/Utility.hpp b/include/Athena/Utility.hpp index 24e68af..ba2f2c9 100644 --- a/include/Athena/Utility.hpp +++ b/include/Athena/Utility.hpp @@ -1,20 +1,4 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - - -#ifndef __UTILITY_H__ +#ifndef __UTILITY_H__ #define __UTILITY_H__ #include diff --git a/src/Athena/Checksums.cpp b/src/Athena/Checksums.cpp index ad7a261..8620502 100644 --- a/src/Athena/Checksums.cpp +++ b/src/Athena/Checksums.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/Checksums.hpp" #include "Athena/FileReader.hpp" #include diff --git a/src/Athena/Compression.cpp b/src/Athena/Compression.cpp index 80dae43..21885c9 100644 --- a/src/Athena/Compression.cpp +++ b/src/Athena/Compression.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/Compression.hpp" #include "Athena/Exception.hpp" #include diff --git a/src/Athena/FileReader.cpp b/src/Athena/FileReader.cpp index 1751417..55cb87d 100644 --- a/src/Athena/FileReader.cpp +++ b/src/Athena/FileReader.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/FileReader.hpp" #include "Athena/FileNotFoundException.hpp" #include "Athena/InvalidDataException.hpp" @@ -316,9 +301,48 @@ bool FileReader::readBool() return (readByte() != 0); } +atVec3f FileReader::readVec3f() +{ + if (!isOpen()) + THROW_INVALID_OPERATION_EXCEPTION_RETURN({}, "File not open for reading"); + + m_bitValid = false; + atVec3f val = {}; + fread(&val, 1, 12, m_fileHandle); + + if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian())) + { + val.vec[0] = utility::swapFloat(val.vec[0]); + val.vec[1] = utility::swapFloat(val.vec[1]); + val.vec[2] = utility::swapFloat(val.vec[2]); + } + + return val; +} + +atVec4f FileReader::readVec4f() +{ + if (!isOpen()) + THROW_INVALID_OPERATION_EXCEPTION_RETURN({}, "File not open for reading"); + + m_bitValid = false; + atVec4f val = {}; + fread(&val, 1, 16, m_fileHandle); + + if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian())) + { + val.vec[0] = utility::swapFloat(val.vec[0]); + val.vec[1] = utility::swapFloat(val.vec[1]); + val.vec[2] = utility::swapFloat(val.vec[2]); + val.vec[3] = utility::swapFloat(val.vec[3]); + } + + return val; +} + std::string FileReader::readString(atInt32 maxlen) { - std::string ret = ""; + std::string ret; atUint8 chr = readByte(); atInt32 i = 0; @@ -336,6 +360,26 @@ std::string FileReader::readString(atInt32 maxlen) return ret; } +std::wstring FileReader::readWString(atInt32 maxlen) +{ + std::wstring ret; + atUint16 chr = readUint16(); + + atInt32 i = 0; + + while (chr != 0) + { + if (maxlen >= 0 && i >= maxlen - 1) + break; + + ret += chr; + chr = readUint16(); + i++; + } + + return ret; +} + std::string FileReader::readUnicode(atInt32 maxlen) { if (!isOpen()) diff --git a/src/Athena/FileWriter.cpp b/src/Athena/FileWriter.cpp index fe919aa..cd9a0ee 100644 --- a/src/Athena/FileWriter.cpp +++ b/src/Athena/FileWriter.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/FileWriter.hpp" #include "Athena/FileNotFoundException.hpp" #include "Athena/InvalidDataException.hpp" @@ -276,6 +261,43 @@ void FileWriter::writeBool(bool val) writeByte(val); } +void FileWriter::writeVec3f(atVec3f vec) +{ + if (!isOpen()) + THROW_INVALID_OPERATION_EXCEPTION("File not open for writing"); + + m_bitValid = false; + + if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian())) + { + vec.vec[0] = utility::swapFloat(vec.vec[0]); + vec.vec[1] = utility::swapFloat(vec.vec[1]); + vec.vec[2] = utility::swapFloat(vec.vec[2]); + } + + if (fwrite(&vec, 1, 12, m_fileHandle) != 12) + THROW_IO_EXCEPTION("Unable to write to stream"); +} + +void FileWriter::writeVec4f(atVec4f vec) +{ + if (!isOpen()) + THROW_INVALID_OPERATION_EXCEPTION("File not open for writing"); + + m_bitValid = false; + + if ((!utility::isSystemBigEndian() && isBigEndian()) || (utility::isSystemBigEndian() && isLittleEndian())) + { + vec.vec[0] = utility::swapFloat(vec.vec[0]); + vec.vec[1] = utility::swapFloat(vec.vec[1]); + vec.vec[2] = utility::swapFloat(vec.vec[2]); + vec.vec[3] = utility::swapFloat(vec.vec[3]); + } + + if (fwrite(&vec, 1, 16, m_fileHandle) != 16) + THROW_IO_EXCEPTION("Unable to write to stream"); +} + void FileWriter::writeString(const std::string& val) { if (!isOpen()) @@ -292,6 +314,22 @@ void FileWriter::writeString(const std::string& val) THROW_IO_EXCEPTION("Unable to write to stream"); } +void FileWriter::writeWString(const std::wstring& val) +{ + if (!isOpen()) + THROW_INVALID_OPERATION_EXCEPTION("File not open for writing"); + + m_bitValid = false; + + wchar_t term = L'\0'; + + if (fwrite(val.c_str(), 2, val.length(), m_fileHandle) != val.length()) + THROW_IO_EXCEPTION("Unable to write to stream"); + + if (fwrite(&term, 2, 1, m_fileHandle) != 1) + THROW_IO_EXCEPTION("Unable to write to stream"); +} + void FileWriter::writeUnicode(const std::string& str) { if (!isOpen()) diff --git a/src/Athena/Global.cpp b/src/Athena/Global.cpp index b100581..b88d92c 100644 --- a/src/Athena/Global.cpp +++ b/src/Athena/Global.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/Global.hpp" std::ostream& operator<<(std::ostream& os, const Athena::SeekOrigin& origin) diff --git a/src/Athena/MemoryReader.cpp b/src/Athena/MemoryReader.cpp index 6d7e4f7..f9c9792 100644 --- a/src/Athena/MemoryReader.cpp +++ b/src/Athena/MemoryReader.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/MemoryReader.hpp" #include "Athena/IOException.hpp" #include "Athena/FileNotFoundException.hpp" @@ -434,6 +419,74 @@ bool MemoryReader::readBool() return ret; } +atVec3f MemoryReader::readVec3f() +{ + if (!m_data) + loadData(); + + if (m_bitPosition > 0) + { + m_bitPosition = 0; + m_position += sizeof(atUint8); + } + + if (m_position + 12 > m_length) + THROW_IO_EXCEPTION_RETURN({}, "Position %0.8X outside stream bounds ", m_position); + + float* source = (float*)(m_data + m_position); + atVec3f result = {source[0], source[1], source[2]}; + if (isBigEndian()) + { + utility::BigFloat(result.vec[0]); + utility::BigFloat(result.vec[1]); + utility::BigFloat(result.vec[2]); + } + else + { + utility::LittleFloat(result.vec[0]); + utility::LittleFloat(result.vec[1]); + utility::LittleFloat(result.vec[2]); + } + + m_position += 12; + return result; +} + +atVec4f MemoryReader::readVec4f() +{ + if (!m_data) + loadData(); + + if (m_bitPosition > 0) + { + m_bitPosition = 0; + m_position += sizeof(atUint8); + } + + if (m_position + 16 > m_length) + THROW_IO_EXCEPTION_RETURN({}, "Position %0.8X outside stream bounds ", m_position); + + float* source = (float*)(m_data + m_position); + atVec4f result = {source[0], source[1], source[2], source[3]}; + if (isBigEndian()) + { + utility::BigFloat(result.vec[0]); + utility::BigFloat(result.vec[1]); + utility::BigFloat(result.vec[2]); + utility::BigFloat(result.vec[3]); + } + else + { + utility::LittleFloat(result.vec[0]); + utility::LittleFloat(result.vec[1]); + utility::LittleFloat(result.vec[2]); + utility::LittleFloat(result.vec[3]); + } + + m_position += 16; + return result; +} + std::string MemoryReader::readUnicode(atInt32 maxlen) { if (!m_data) @@ -464,7 +517,7 @@ std::string MemoryReader::readUnicode(atInt32 maxlen) std::string MemoryReader::readString(atInt32 maxlen) { - std::string ret = ""; + std::string ret; atUint8 chr = readByte(); atInt32 i = 0; @@ -482,6 +535,26 @@ std::string MemoryReader::readString(atInt32 maxlen) return ret; } +std::wstring MemoryReader::readWString(atInt32 maxlen) +{ + std::wstring ret; + atUint16 chr = readUint16(); + + atInt32 i = 0; + + while (chr != 0) + { + if (maxlen >= 0 && i >= maxlen - 1) + break; + + ret += chr; + chr = readUint16(); + i++; + } + + return ret; +} + void MemoryReader::setProgressCallback(std::function cb) { m_progressCallback = cb; diff --git a/src/Athena/MemoryWriter.cpp b/src/Athena/MemoryWriter.cpp index ba8304f..82d035b 100644 --- a/src/Athena/MemoryWriter.cpp +++ b/src/Athena/MemoryWriter.cpp @@ -1,18 +1,3 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - #include "Athena/MemoryWriter.hpp" #include "Athena/IOException.hpp" #include "Athena/InvalidOperationException.hpp" @@ -443,6 +428,75 @@ void MemoryWriter::writeBool(bool val) m_position += sizeof(bool); } +void MemoryWriter::writeVec3f(atVec3f vec) +{ + if (!isOpen()) + resize(12); + + if (m_bitPosition > 0) + { + m_bitPosition = 0; + m_position += sizeof(atUint8); + } + + if (m_position + 12 > m_length) + resize(m_position + 12); + + if (isBigEndian()) + { + utility::BigFloat(vec.vec[0]); + utility::BigFloat(vec.vec[1]); + utility::BigFloat(vec.vec[2]); + } + else + { + utility::LittleFloat(vec.vec[0]); + utility::LittleFloat(vec.vec[1]); + utility::LittleFloat(vec.vec[2]); + } + + ((float*)(m_data + m_position))[0] = vec.vec[0]; + ((float*)(m_data + m_position))[1] = vec.vec[1]; + ((float*)(m_data + m_position))[2] = vec.vec[2]; + m_position += 12; +} + +void MemoryWriter::writeVec4f(atVec4f vec) +{ + if (!isOpen()) + resize(16); + + if (m_bitPosition > 0) + { + m_bitPosition = 0; + m_position += sizeof(atUint8); + } + + if (m_position + 16 > m_length) + resize(m_position + 16); + + if (isBigEndian()) + { + utility::BigFloat(vec.vec[0]); + utility::BigFloat(vec.vec[1]); + utility::BigFloat(vec.vec[2]); + utility::BigFloat(vec.vec[3]); + } + else + { + utility::LittleFloat(vec.vec[0]); + utility::LittleFloat(vec.vec[1]); + utility::LittleFloat(vec.vec[2]); + utility::LittleFloat(vec.vec[3]); + } + + ((float*)(m_data + m_position))[0] = vec.vec[0]; + ((float*)(m_data + m_position))[1] = vec.vec[1]; + ((float*)(m_data + m_position))[2] = vec.vec[2]; + ((float*)(m_data + m_position))[3] = vec.vec[3]; + m_position += 16; +} + void MemoryWriter::writeUnicode(const std::string& str) { std::string tmpStr = "\xEF\xBB\xBF" + str; @@ -473,6 +527,19 @@ void MemoryWriter::writeString(const std::string& str) writeUByte(0); } +void MemoryWriter::writeWString(const std::wstring& str) +{ + for (atUint16 c : str) + { + writeUint16(c); + + if (c == L'\0') + break; + } + + writeUint16(0); +} + void MemoryWriter::fill(atUint8 val, atUint64 length) { while ((length--) > 0) diff --git a/src/Athena/Utility.cpp b/src/Athena/Utility.cpp index 2374d0b..e925b59 100644 --- a/src/Athena/Utility.cpp +++ b/src/Athena/Utility.cpp @@ -1,19 +1,4 @@ -// This file is part of libAthena. -// -// libAthena is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// libAthena is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with libAthena. If not, see - -#include "Athena/Utility.hpp" +#include "Athena/Utility.hpp" #include #include #include