diff --git a/AthenaCore.pri b/AthenaCore.pri index 3a30e01..2b43eed 100644 --- a/AthenaCore.pri +++ b/AthenaCore.pri @@ -62,7 +62,8 @@ HEADERS += \ $$PWD/include/utf8/unchecked.h \ $$PWD/include/Athena/FileInfo.hpp \ $$PWD/include/Athena/Dir.hpp \ - $$PWD/include/gekko_support.h + $$PWD/include/gekko_support.h \ + $$PWD/include/Athena/DNA.hpp win32:HEADERS += \ $$PWD/include/win32_largefilewrapper.h diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9d8ae20 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011-2015 Phillip "Antidote" Stephens, Jack Andersen, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/PKGBUILD b/PKGBUILD index b64c4c6..5172e21 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,13 +1,13 @@ # PKGBUILD for libAthena _pkgname=libathena pkgname=$_pkgname-git -pkgver=v1.0.0 +pkgver=1.1.0.17.gfb722a9 pkgrel=1 pkgdesc="Basic cross platform IO library" arch=('i686' 'x86_64') source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") options=(staticlibs) -license="GPL3" +license="MIT" makedepends=('git qt5-base sed') md5sums=('SKIP') sha256sums=('SKIP') @@ -19,7 +19,7 @@ pkgver() { build() { cd "$srcdir/$_pkgname" - qmake && make + qmake PREFIX="$pkgdir/usr" && make } package() { diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD new file mode 100644 index 0000000..5c49e19 --- /dev/null +++ b/atdna/PKGBUILD @@ -0,0 +1,30 @@ +# PKGBUILD for atdna +_pkgname=atdna +pkgname=$_pkgname-git +pkgver=1.1.0.23.g647f9c4 +pkgrel=1 +pkgdesc="Companion DNA utility for libAthena" +arch=('i686' 'x86_64') +source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") +options=(staticlibs) +license="MIT" +makedepends=('git qt5-base sed clang libathena-git') +depends=('libathena-git') +md5sums=('SKIP') +sha256sums=('SKIP') + +pkgver() { + cd "$srcdir/$_pkgname" + git describe --tags | sed 's|-|.|g' +} + +build() { + cd "$srcdir/$_pkgname/atdna" + qmake PREFIX="$pkgdir/usr" INSTALL_PREFIX="/usr" && make +} + +package() { + cd "$srcdir/$_pkgname/atdna" + qmake PREFIX="$pkgdir/usr" INSTALL_PREFIX="/usr" && make install +} + diff --git a/atdna/atdna.pro b/atdna/atdna.pro new file mode 100644 index 0000000..e6b7a11 --- /dev/null +++ b/atdna/atdna.pro @@ -0,0 +1,60 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt +QT = +DEFINES += __STDC_LIMIT_MACROS=1 __STDC_CONSTANT_MACROS=1 +QMAKE_CXXFLAGS += -fno-rtti +QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter + +INCLUDEPATH += ../include + +CONFIG(debug, debug|release) { + # FOR FULL DEBUGGING, PLEASE UNCOMMENT THESE AND POINT THEM TO + # THE INSTALL PREFIX OF YOUR OWN DEBUG BUILD OF LLVM/CLANG!! + #INCLUDEPATH += /home/jacko/llvm-build/usr/include + #LIBS += -L/home/jacko/llvm-build/usr/lib + LIBS += -g +} else { + LIBS += -flto +} + +SOURCES += \ + main.cpp + +LIBS += -lclangFrontend -lclangTooling -lclangDriver \ + -lclangSerialization -lclangParse -lclangSema \ + -lclangAnalysis -lclangEdit \ + -lclangAST -lclangLex -lclangBasic \ + -lLLVMOption -lLLVMMCParser -lLLVMBitReader \ + -lLLVMMC -lLLVMSupport -lz -lpthread -lcurses -ldl + +HEADERS += \ + test.hpp + +unix { + isEmpty(PREFIX) { + PREFIX = /usr/local + } + isEmpty(INSTALL_PREFIX) { + INSTALL_PREFIX = /usr/local + } + utilFiles.path = $$PREFIX/bin + utilFiles.files = $$OUT_PWD/atdna + INSTALLS += utilFiles +} + +win32 { + isEmpty(PREFIX) { + PREFIX = $$PWD/pkg + } + isEmpty(INSTALL_PREFIX) { + INSTALL_PREFIX = $$PWD/pkg + } + utilFiles.path = $$PREFIX/bin + utilFiles.files = $$OUT_PWD/atdna + INSTALLS += utilFiles +} + +DEFINES += INSTALL_PREFIX="$$INSTALL_PREFIX" + diff --git a/atdna/main.cpp b/atdna/main.cpp new file mode 100644 index 0000000..9cb6439 --- /dev/null +++ b/atdna/main.cpp @@ -0,0 +1,456 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Tooling.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/DeclCXX.h" +#include "clang/Basic/Version.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/CommandLine.h" + +#ifndef INSTALL_PREFIX +#define INSTALL_PREFIX /usr/local +#endif +#define XSTR(s) STR(s) +#define STR(s) #s + +static llvm::cl::opt Help("h", llvm::cl::desc("Alias for -help"), llvm::cl::Hidden); + +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::list InputFilenames(llvm::cl::Positional, + llvm::cl::desc(""), + llvm::cl::OneOrMore); + +class ATDNAEmitVisitor : public clang::RecursiveASTVisitor +{ + clang::ASTContext& context; + llvm::raw_fd_ostream& fileOut; + + std::string GetOpString(const clang::Type* theType, unsigned width, + std::string fieldName, bool writerPass) + { + if (writerPass) + { + if (theType->isBuiltinType()) + { + const clang::BuiltinType* bType = (clang::BuiltinType*)theType; + if (bType->isUnsignedInteger()) + { + if (width == 8) + return "writer.writeUByte(" + fieldName + ");"; + else if (width == 16) + return "writer.writeUint16(" + fieldName + ");"; + else if (width == 32) + return "writer.writeUint32(" + fieldName + ");"; + else if (width == 64) + return "writer.writeUint64(" + fieldName + ");"; + } + else if (bType->isSignedInteger()) + { + if (width == 8) + return "writer.writeByte(" + fieldName + ");"; + else if (width == 16) + return "writer.writeInt16(" + fieldName + ");"; + else if (width == 32) + return "writer.writeInt32(" + fieldName + ");"; + else if (width == 64) + return "writer.writeInt64(" + fieldName + ");"; + } + else if (bType->isFloatingPoint()) + { + if (width == 32) + return "writer.writeFloat(" + fieldName + ");"; + else if (width == 64) + return "writer.writeDouble(" + fieldName + ");"; + } + } + else if (theType->isRecordType()) + { + const clang::RecordDecl* rDecl = ((clang::RecordType*)theType)->getDecl(); + for (const clang::FieldDecl* field : rDecl->fields()) + { + if (!field->getNameAsString().compare("clangVec")) + { + const clang::VectorType* vType = (clang::VectorType*)field->getType().getTypePtr(); + if (vType->isVectorType()) + { + const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + if (!eType->isBuiltinType() || !eType->isFloatingPoint() || + context.getTypeInfo(eType).Width != 32) + continue; + if (vType->getNumElements() == 3) + return "writer.writeVec3f(" + fieldName + ");"; + else if (vType->getNumElements() == 4) + return "writer.writeVec4f(" + fieldName + ");"; + } + } + } + } + } + else + { + if (theType->isBuiltinType()) + { + const clang::BuiltinType* bType = (clang::BuiltinType*)theType; + if (bType->isUnsignedInteger()) + { + if (width == 8) + return "reader.readUByte()"; + else if (width == 16) + return "reader.readUint16()"; + else if (width == 32) + return "reader.readUint32()"; + else if (width == 64) + return "reader.readUint64()"; + } + else if (bType->isSignedInteger()) + { + if (width == 8) + return "reader.readByte()"; + else if (width == 16) + return "reader.readInt16()"; + else if (width == 32) + return "reader.readInt32()"; + else if (width == 64) + return "reader.readInt64()"; + } + else if (bType->isFloatingPoint()) + { + if (width == 32) + return "reader.readFloat()"; + else if (width == 64) + return "reader.readDouble()"; + } + } + else if (theType->isRecordType()) + { + const clang::RecordDecl* rDecl = ((clang::RecordType*)theType)->getDecl(); + for (const clang::FieldDecl* field : rDecl->fields()) + { + if (!field->getNameAsString().compare("clangVec")) + { + const clang::VectorType* vType = (clang::VectorType*)field->getType().getTypePtr(); + if (vType->isVectorType()) + { + const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + if (!eType->isBuiltinType() || !eType->isFloatingPoint() || + context.getTypeInfo(eType).Width != 32) + continue; + if (vType->getNumElements() == 3) + return "reader.readVec3f()"; + else if (vType->getNumElements() == 4) + return "reader.readVec4f()"; + } + } + } + } + } + return std::string(); + } + +public: + explicit ATDNAEmitVisitor(clang::ASTContext& ctxin, + llvm::raw_fd_ostream& fo) + : context(ctxin), fileOut(fo) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) + { + if (decl->isInvalidDecl() || !decl->hasDefinition()) + return true; + + if (!decl->getNumBases()) + return true; + + /* First ensure this inherits from struct Athena::io::DNA */ + bool foundDNA = false; + for (const clang::CXXBaseSpecifier& base : decl->bases()) + { + clang::QualType canonType = base.getType().getCanonicalType(); + if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) + { + foundDNA = true; + break; + } + } + if (!foundDNA) + return true; + + for (int p=0 ; p<2 ; ++p) + { + if (p) + fileOut << "void " << decl->getQualifiedNameAsString() << "::write(Athena::IStreamWriter& writer) const\n{\n"; + else + fileOut << "void " << decl->getQualifiedNameAsString() << "::read(Athena::IStreamReader& reader)\n{\n"; + int currentEndian = -1; + + for (const clang::FieldDecl* field : decl->fields()) + { + clang::QualType qualType = field->getType(); + clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); + const clang::Type* regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::Elaborated) + regType = regType->getUnqualifiedDesugaredType(); + + 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")) + { + int endian = -1; + 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(); + llvm::APSInt result; + if (defArg->isIntegerConstantExpr(result, context)) + endian = result.getSExtValue(); + } + } + + std::string ioOp; + const clang::TemplateArgument* typeArg = nullptr; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); + ioOp = GetOpString(type, regTypeInfo.Width, field->getName().str(), p); + } + 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(tsDecl->getLocation(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error")); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + if (typeArg) + diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*typeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); + continue; + } + + 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; + } + + if (!p) + fileOut << " " << field->getName() << " = " << ioOp << ";\n"; + else + fileOut << " " << ioOp << "\n"; + } + 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(); + } + } + + std::string ioOp; + std::string sizeVar; + const clang::TemplateArgument* typeArg = nullptr; + const clang::TemplateArgument* sizeArg = nullptr; + size_t idx = 0; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); + clang::TypeInfo typeInfo = context.getTypeInfo(arg.getAsType().getCanonicalType()); + ioOp = GetOpString(type, typeInfo.Width, "*it", p); + } + 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(); + if (argExpr->getStmtClass() == clang::Stmt::DeclRefExprClass) + { + const clang::DeclRefExpr* refExpr = (clang::DeclRefExpr*)argExpr; + sizeVar = refExpr->getFoundDecl()->getNameAsString(); + } + } + } + else if (idx == 2) + { + llvm::APSInt value; + if (expr->isIntegerConstantExpr(value, context)) + endian = value.getSExtValue(); + } + } + ++idx; + } + + if (ioOp.empty()) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error")); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + if (typeArg) + diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*typeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); + continue; + } + + if (sizeVar.empty()) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error")); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + if (sizeArg) + diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*sizeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); + continue; + } + + 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; + } + + if (!p) + { + fileOut << " " << field->getName() << ".clear();\n"; + fileOut << " " << field->getName() << ".reserve(" << sizeVar << ");\n"; + fileOut << " for (int i=0 ; i<" << sizeVar << " ; ++i)\n " << field->getName() << ".push_back(" << ioOp << ");\n"; + } + else + fileOut << " for (int i=0, auto it=" << field->getName() << ".begin() ; i<" << sizeVar << " && it!=" << field->getName() << ".end() ; ++i, ++it)\n " << ioOp << "\n"; + + } + + } + + else if (regType->getTypeClass() == clang::Type::Record) + { + const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); + if (cxxRDecl) + { + for (const clang::CXXBaseSpecifier& base : cxxRDecl->bases()) + { + clang::QualType canonType = base.getType().getCanonicalType(); + if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) + { + fileOut << " " << field->getNameAsString() << (p ? ".write(writer);\n" : ".read(reader);\n"); + currentEndian = -1; + break; + } + } + } + } + + } + + fileOut << "}\n\n"; + + } + + return true; + } +}; + +class ATDNAConsumer : public clang::ASTConsumer +{ + ATDNAEmitVisitor emitVisitor; + llvm::raw_fd_ostream& fileOut; +public: + explicit ATDNAConsumer(clang::ASTContext& context, llvm::raw_fd_ostream& fo) + : emitVisitor(context, fo), + fileOut(fo) {} + void HandleTranslationUnit(clang::ASTContext& context) + { + /* Write file head */ + fileOut << "/* Auto generated atdna implementation */\n" + "#include \n" + "#include \n" + "#include \n\n"; + for (const std::string& inputf : InputFilenames) + fileOut << "#include \"" << inputf << "\"\n"; + fileOut << "\n"; + + /* Second pass - emit file */ + emitVisitor.TraverseDecl(context.getTranslationUnitDecl()); + } +}; + +class ATDNAAction : public clang::ASTFrontendAction +{ +public: + explicit ATDNAAction() {} + std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, + llvm::StringRef /*filename*/) + { + llvm::raw_fd_ostream* fileout; + if (OutputFilename.size()) + fileout = compiler.createOutputFile(OutputFilename, false, true, "", "", true); + else + fileout = compiler.createDefaultOutputFile(false, "a", "cpp"); + return std::unique_ptr(new ATDNAConsumer(compiler.getASTContext(), *fileout)); + } +}; + + +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", + "-fsyntax-only", + "-std=c++11"}; + args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/lib/clang/" + CLANG_VERSION_STRING + "/include"); + args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/include/Athena"); + for (int a=1 ; a fman(new clang::FileManager(clang::FileSystemOptions())); + clang::tooling::ToolInvocation TI(args, new ATDNAAction, fman.get()); + if (TI.run()) + return 0; + + return -1; +} + diff --git a/atdna/test.hpp b/atdna/test.hpp new file mode 100644 index 0000000..7d7d97f --- /dev/null +++ b/atdna/test.hpp @@ -0,0 +1,32 @@ +#include + +using namespace Athena; + +struct ANCSSubFile : public io::DNA +{ + DECL_DNA + Value sub1; + Value sub2; +}; + +struct ANCSFile : public io::DNA +{ + DECL_DNA + Value var32; + Value var16; + Value vec3; + Value vec4; + + struct ANCSNestedSubFile : public io::DNA + { + DECL_DNA + Value nestSub1; + Value nestSub2; + } nestedSubFile; + + ANCSSubFile subFile; + + Value arrCount; + Vector array; +}; + diff --git a/include/Athena/DNA.hpp b/include/Athena/DNA.hpp new file mode 100644 index 0000000..31ad754 --- /dev/null +++ b/include/Athena/DNA.hpp @@ -0,0 +1,43 @@ +#ifndef DNA_HPP +#define DNA_HPP + +#include "Global.hpp" +#include "IStreamReader.hpp" +#include "IStreamWriter.hpp" +#include +#include + +namespace Athena +{ +namespace io +{ + +/** + * @brief Base DNA class used against 'atdna' + * + * Athena bundles a build-tool called 'atdna'. This tool functions + * just like the 'clang' compiler, except it emits + */ +template +struct DNA +{ + template + using Value = T; + + template + using Vector = std::vector; + + virtual void read(IStreamReader&)=0; + virtual void write(IStreamWriter&) const=0; +}; + +/** Macro to automatically declare read/write methods in subclasses */ +#define DECL_DNA \ + void read(Athena::io::IStreamReader&); \ + void write(Athena::io::IStreamWriter&) const; \ + +} +} + +#endif // DNA_HPP + diff --git a/include/Athena/Global.hpp b/include/Athena/Global.hpp index df93ac5..c9b6d16 100644 --- a/include/Athena/Global.hpp +++ b/include/Athena/Global.hpp @@ -73,14 +73,14 @@ typedef struct stat64 stat64_t; namespace Athena { -enum class SeekOrigin +enum SeekOrigin { Begin, Current, End }; -enum class Endian +enum Endian { LittleEndian, BigEndian diff --git a/include/Athena/Types.hpp b/include/Athena/Types.hpp index 7e55f11..53445df 100644 --- a/include/Athena/Types.hpp +++ b/include/Athena/Types.hpp @@ -56,6 +56,34 @@ typedef unsigned long atUint32; typedef signed long long atInt64; typedef unsigned long long atUint64; +// Vector types +#if __SSE__ +#include +#endif + +typedef union +{ +#if __clang__ + float clangVec __attribute__((__vector_size__(12))); +#endif +#if __SSE__ + __m128 mVec128; +#endif + float vec[3]; +} atVec3f; + +typedef union +{ +#if __clang__ + float clangVec __attribute__((__vector_size__(16))); +#endif +#if __SSE__ + __m128 mVec128; +#endif + float vec[4]; +} atVec4f; + + #ifndef NULL #ifdef __cplusplus #define NULL 0