mirror of https://github.com/libAthena/athena.git
Merge branch 'master' of ssh://git.axiodl.com:6431/libAthena/athena
This commit is contained in:
commit
42581c922a
|
@ -19,19 +19,6 @@ set(ATHENA_VERSION
|
||||||
|
|
||||||
add_subdirectory(extern)
|
add_subdirectory(extern)
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
list(APPEND CORE_EXTRA src/win32_largefilewrapper.c include/win32_largefilewrapper.h
|
|
||||||
src/athena/FileWriterWin32.cpp src/athena/FileReaderWin32.cpp)
|
|
||||||
else()
|
|
||||||
list(APPEND CORE_EXTRA src/athena/FileWriterNix.cpp src/athena/FileReader.cpp)
|
|
||||||
if(APPLE OR GEKKO OR NX OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
|
||||||
list(APPEND CORE_EXTRA src/osx_largefilewrapper.c include/osx_largefilewrapper.h)
|
|
||||||
if(GEKKO OR NX)
|
|
||||||
list(APPEND CORE_EXTRA src/gekko_support.c include/gekko_support.h)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(athena-core
|
add_library(athena-core
|
||||||
src/athena/Utility.cpp
|
src/athena/Utility.cpp
|
||||||
src/athena/MemoryReader.cpp
|
src/athena/MemoryReader.cpp
|
||||||
|
@ -49,7 +36,6 @@ add_library(athena-core
|
||||||
src/athena/FileInfo.cpp
|
src/athena/FileInfo.cpp
|
||||||
src/athena/Dir.cpp
|
src/athena/Dir.cpp
|
||||||
src/athena/DNAYaml.cpp
|
src/athena/DNAYaml.cpp
|
||||||
${CORE_EXTRA}
|
|
||||||
|
|
||||||
include/athena/IStream.hpp
|
include/athena/IStream.hpp
|
||||||
include/athena/IStreamReader.hpp
|
include/athena/IStreamReader.hpp
|
||||||
|
@ -81,10 +67,46 @@ add_library(athena-core
|
||||||
include/yaml.h
|
include/yaml.h
|
||||||
include/utf8proc.h
|
include/utf8proc.h
|
||||||
)
|
)
|
||||||
|
if(WIN32)
|
||||||
|
target_sources(athena-core PRIVATE
|
||||||
|
src/win32_largefilewrapper.c
|
||||||
|
include/win32_largefilewrapper.h
|
||||||
|
src/athena/FileWriterWin32.cpp
|
||||||
|
src/athena/FileReaderWin32.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(athena-core PRIVATE
|
||||||
|
-DNOMINMAX
|
||||||
|
-DWIN32_LEAN_AND_MEAN
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
target_sources(athena-core PRIVATE
|
||||||
|
src/athena/FileWriterNix.cpp
|
||||||
|
src/athena/FileReader.cpp
|
||||||
|
)
|
||||||
|
if(APPLE OR GEKKO OR NX OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
|
target_sources(athena-core PRIVATE
|
||||||
|
src/osx_largefilewrapper.c
|
||||||
|
include/osx_largefilewrapper.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if(GEKKO OR NX)
|
||||||
|
target_sources(athena-core PRIVATE
|
||||||
|
src/gekko_support.c
|
||||||
|
include/gekko_support.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(athena-core PUBLIC
|
target_include_directories(athena-core PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
$<BUILD_INTERFACE:${ZLIB_INCLUDE_DIR}>)
|
$<BUILD_INTERFACE:${ZLIB_INCLUDE_DIR}>
|
||||||
target_link_libraries(athena-core PUBLIC athena-libyaml fmt)
|
)
|
||||||
|
target_link_libraries(athena-core PUBLIC
|
||||||
|
athena-libyaml
|
||||||
|
fmt
|
||||||
|
)
|
||||||
|
|
||||||
add_library(athena-sakura EXCLUDE_FROM_ALL
|
add_library(athena-sakura EXCLUDE_FROM_ALL
|
||||||
src/athena/Sprite.cpp
|
src/athena/Sprite.cpp
|
||||||
|
|
229
atdna/main.cpp
229
atdna/main.cpp
|
@ -1,19 +1,22 @@
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <memory>
|
||||||
#include "clang/AST/ASTConsumer.h"
|
#include <string>
|
||||||
#include "clang/AST/RecursiveASTVisitor.h"
|
#include <utility>
|
||||||
#include "clang/Frontend/CompilerInstance.h"
|
#include <vector>
|
||||||
#include "clang/Frontend/FrontendAction.h"
|
|
||||||
#include "clang/Frontend/Utils.h"
|
#include <clang/AST/ASTConsumer.h>
|
||||||
#include "clang/Tooling/Tooling.h"
|
#include <clang/AST/DeclCXX.h>
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include <clang/AST/RecursiveASTVisitor.h>
|
||||||
#include "clang/Sema/Sema.h"
|
#include <clang/Basic/Version.h>
|
||||||
#include "clang/AST/RecordLayout.h"
|
#include <clang/Frontend/CompilerInstance.h>
|
||||||
#include "clang/AST/DeclCXX.h"
|
#include <clang/Frontend/FrontendAction.h>
|
||||||
#include "clang/AST/TypeLoc.h"
|
#include <clang/Frontend/Utils.h>
|
||||||
#include "clang/Basic/Version.h"
|
#include <clang/Sema/Sema.h>
|
||||||
#include "llvm/Support/Format.h"
|
#include <clang/Tooling/Tooling.h>
|
||||||
#include "llvm/Support/CommandLine.h"
|
|
||||||
|
#include <llvm/Support/CommandLine.h>
|
||||||
|
#include <llvm/Support/Format.h>
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
|
@ -134,15 +137,15 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
const auto* vType = static_cast<const clang::VectorType*>(field->getType().getTypePtr());
|
const auto* vType = static_cast<const clang::VectorType*>(field->getType().getTypePtr());
|
||||||
if (vType->isVectorType()) {
|
if (vType->isVectorType()) {
|
||||||
const auto* eType = static_cast<const clang::BuiltinType*>(vType->getElementType().getTypePtr());
|
const auto* eType = static_cast<const clang::BuiltinType*>(vType->getElementType().getTypePtr());
|
||||||
const uint64_t width = context.getTypeInfo(eType).Width;
|
const uint64_t typeWidth = context.getTypeInfo(eType).Width;
|
||||||
if (!eType->isBuiltinType() || !eType->isFloatingPoint() || (width != 32 && width != 64))
|
if (!eType->isBuiltinType() || !eType->isFloatingPoint() || (typeWidth != 32 && typeWidth != 64))
|
||||||
continue;
|
continue;
|
||||||
if (vType->getNumElements() == 2) {
|
if (vType->getNumElements() == 2) {
|
||||||
return width / 8 * 2;
|
return typeWidth / 8 * 2;
|
||||||
} else if (vType->getNumElements() == 3) {
|
} else if (vType->getNumElements() == 3) {
|
||||||
return width / 8 * 3;
|
return typeWidth / 8 * 3;
|
||||||
} else if (vType->getNumElements() == 4) {
|
} else if (vType->getNumElements() == 4) {
|
||||||
return width / 8 * 4;
|
return typeWidth / 8 * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +167,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
|
|
||||||
static std::string GetPropIdExpr(const clang::FieldDecl* field, const std::string& fieldName) {
|
static std::string GetPropIdExpr(const clang::FieldDecl* field, const std::string& fieldName) {
|
||||||
std::string fieldStr = GetFieldString(fieldName);
|
std::string fieldStr = GetFieldString(fieldName);
|
||||||
std::string propIdExpr = "\"" + fieldStr + "\"sv";
|
std::string propIdExpr = "\""s.append(fieldStr).append("\"sv");
|
||||||
for (clang::Attr* attr : field->attrs()) {
|
for (clang::Attr* attr : field->attrs()) {
|
||||||
if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null<clang::AnnotateAttr>(attr)) {
|
if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null<clang::AnnotateAttr>(attr)) {
|
||||||
llvm::StringRef textRef = annot->getAnnotation();
|
llvm::StringRef textRef = annot->getAnnotation();
|
||||||
|
@ -184,22 +187,39 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr,
|
static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr,
|
||||||
const std::string& endianExpr) {
|
const std::string& endianExpr) {
|
||||||
|
|
||||||
return "<Op, "s + endianExpr + ">(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", s)";
|
return "<Op, "s.append(endianExpr)
|
||||||
|
.append(">(athena::io::PropId(")
|
||||||
|
.append(propIdExpr)
|
||||||
|
.append("), ")
|
||||||
|
.append(fieldName)
|
||||||
|
.append(", s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) {
|
static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) {
|
||||||
|
|
||||||
return "<Op>(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", s)";
|
return "<Op>(athena::io::PropId("s.append(propIdExpr).append("), ").append(fieldName).append(", s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr,
|
static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr,
|
||||||
const std::string& sizeExpr, const std::string& endianExpr) {
|
const std::string& sizeExpr, const std::string& endianExpr) {
|
||||||
return "<Op, "s + endianExpr + ">(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", " + sizeExpr + ", s)";
|
return "<Op, "s.append(endianExpr)
|
||||||
|
.append(">(athena::io::PropId(")
|
||||||
|
.append(propIdExpr)
|
||||||
|
.append("), ")
|
||||||
|
.append(fieldName)
|
||||||
|
.append(", ")
|
||||||
|
.append(sizeExpr)
|
||||||
|
.append(", s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr,
|
static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr,
|
||||||
const std::string& sizeExpr) {
|
const std::string& sizeExpr) {
|
||||||
return "<Op>(athena::io::PropId(" + propIdExpr + "), " + fieldName + ", " + sizeExpr + ", s)";
|
return "<Op>(athena::io::PropId("s.append(propIdExpr)
|
||||||
|
.append("), ")
|
||||||
|
.append(fieldName)
|
||||||
|
.append(", ")
|
||||||
|
.append(sizeExpr)
|
||||||
|
.append(", s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RecurseNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) {
|
static void RecurseNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) {
|
||||||
|
@ -220,7 +240,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
templateStmt += ", ";
|
templateStmt += ", ";
|
||||||
qualType += ", ";
|
qualType += ", ";
|
||||||
}
|
}
|
||||||
templateStmt += "class "s + tpParm->getName().data();
|
templateStmt += "class "s.append(tpParm->getName().str());
|
||||||
qualType += tpParm->getName();
|
qualType += tpParm->getName();
|
||||||
needsComma = true;
|
needsComma = true;
|
||||||
} else if (const clang::NonTypeTemplateParmDecl* nonTypeParm =
|
} else if (const clang::NonTypeTemplateParmDecl* nonTypeParm =
|
||||||
|
@ -229,7 +249,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
templateStmt += ", ";
|
templateStmt += ", ";
|
||||||
qualType += ", ";
|
qualType += ", ";
|
||||||
}
|
}
|
||||||
templateStmt += nonTypeParm->getType().getAsString() + ' ' + nonTypeParm->getName().data();
|
templateStmt += nonTypeParm->getType().getAsString().append(1, ' ').append(nonTypeParm->getName().str());
|
||||||
qualType += nonTypeParm->getName();
|
qualType += nonTypeParm->getName();
|
||||||
needsComma = true;
|
needsComma = true;
|
||||||
}
|
}
|
||||||
|
@ -277,10 +297,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
int numTuples = int(specParms.size()) / numParms;
|
int numTuples = int(specParms.size()) / numParms;
|
||||||
for (const auto& parent : parentSpecializations) {
|
for (const auto& parent : parentSpecializations) {
|
||||||
for (int i = 0; i < numTuples; ++i) {
|
for (int i = 0; i < numTuples; ++i) {
|
||||||
if (parent.first.empty())
|
if (parent.first.empty()) {
|
||||||
specializations.emplace_back(std::string(rec->getName().data()) + '<', 1);
|
specializations.emplace_back(std::string(rec->getName().str()).append(1, '<'), 1);
|
||||||
else
|
} else {
|
||||||
specializations.emplace_back(parent.first + "::" + rec->getName().data() + '<', parent.second + 1);
|
auto specialization =
|
||||||
|
std::string(parent.first).append("::").append(rec->getName().str()).append(1, '<');
|
||||||
|
specializations.emplace_back(std::move(specialization), parent.second + 1);
|
||||||
|
}
|
||||||
bool needsComma = false;
|
bool needsComma = false;
|
||||||
for (auto it = specParms.begin() + i * numParms;
|
for (auto it = specParms.begin() + i * numParms;
|
||||||
it != specParms.end() && it != specParms.begin() + (i + 1) * numParms; ++it) {
|
it != specParms.end() && it != specParms.begin() + (i + 1) * numParms; ++it) {
|
||||||
|
@ -290,7 +313,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
specializations.back().first += trimmed;
|
specializations.back().first += trimmed;
|
||||||
needsComma = true;
|
needsComma = true;
|
||||||
}
|
}
|
||||||
specializations.back().first += ">";
|
specializations.back().first += '>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foundSpecializations = true;
|
foundSpecializations = true;
|
||||||
|
@ -301,17 +324,21 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundSpecializations)
|
if (!foundSpecializations) {
|
||||||
for (const auto& parent : parentSpecializations) {
|
for (const auto& parent : parentSpecializations) {
|
||||||
if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null<clang::NamedDecl>(decl)) {
|
if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null<clang::NamedDecl>(decl)) {
|
||||||
if (parent.first.empty())
|
if (parent.first.empty()) {
|
||||||
specializations.emplace_back(namedDecl->getName().data(), parent.second);
|
specializations.emplace_back(namedDecl->getName().str(), parent.second);
|
||||||
else
|
} else {
|
||||||
specializations.emplace_back(parent.first + "::" + namedDecl->getName().data(), parent.second);
|
specializations.emplace_back(std::string(parent.first).append("::").append(namedDecl->getName().str()),
|
||||||
} else
|
parent.second);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
specializations.push_back(parent);
|
specializations.push_back(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<std::pair<std::string, int>> GetNestedTypeSpecializations(const clang::DeclContext* decl) {
|
static std::vector<std::pair<std::string, int>> GetNestedTypeSpecializations(const clang::DeclContext* decl) {
|
||||||
std::vector<std::pair<std::string, int>> ret;
|
std::vector<std::pair<std::string, int>> ret;
|
||||||
|
@ -336,8 +363,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
std::string m_fieldName;
|
std::string m_fieldName;
|
||||||
std::string m_ioOp;
|
std::string m_ioOp;
|
||||||
bool m_squelched = false;
|
bool m_squelched = false;
|
||||||
OutputNode(NodeType type, const std::string& fieldName, const std::string& ioOp, bool squelched)
|
OutputNode(NodeType type, std::string fieldName, std::string ioOp, bool squelched)
|
||||||
: m_type(type), m_fieldName(fieldName), m_ioOp(ioOp), m_squelched(squelched) {}
|
: m_type(type), m_fieldName(std::move(fieldName)), m_ioOp(std::move(ioOp)), m_squelched(squelched) {}
|
||||||
};
|
};
|
||||||
std::vector<OutputNode> outputNodes;
|
std::vector<OutputNode> outputNodes;
|
||||||
|
|
||||||
|
@ -389,24 +416,24 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ioOp;
|
std::string ioOp;
|
||||||
bool isDNAType = false;
|
|
||||||
for (const clang::TemplateArgument& arg : *tsType) {
|
for (const clang::TemplateArgument& arg : *tsType) {
|
||||||
if (arg.getKind() == clang::TemplateArgument::Type) {
|
if (arg.getKind() == clang::TemplateArgument::Type) {
|
||||||
if (defaultEndian)
|
if (defaultEndian) {
|
||||||
ioOp = GetOpString(fieldName, propIdExpr);
|
ioOp = GetOpString(fieldName, propIdExpr);
|
||||||
else
|
} else {
|
||||||
ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
|
ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ioOp.empty()) {
|
if (ioOp.empty()) {
|
||||||
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
||||||
diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena");
|
diag.AddString("Unable to use type '"s.append(tsDecl->getName().str()).append("' with Athena"));
|
||||||
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false);
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false);
|
||||||
} else if (tsDecl->getName() == "Vector") {
|
} else if (tsDecl->getName() == "Vector") {
|
||||||
llvm::APSInt endian(64, -1);
|
llvm::APSInt endian(64, -1);
|
||||||
std::string endianExprStr;
|
std::string endianExprStr;
|
||||||
|
@ -457,20 +484,20 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
|
|
||||||
clang::QualType templateType;
|
clang::QualType templateType;
|
||||||
std::string ioOp;
|
std::string ioOp;
|
||||||
bool isDNAType = false;
|
|
||||||
for (const clang::TemplateArgument& arg : *tsType) {
|
for (const clang::TemplateArgument& arg : *tsType) {
|
||||||
if (arg.getKind() == clang::TemplateArgument::Type) {
|
if (arg.getKind() == clang::TemplateArgument::Type) {
|
||||||
templateType = arg.getAsType().getCanonicalType();
|
templateType = arg.getAsType().getCanonicalType();
|
||||||
if (defaultEndian)
|
if (defaultEndian) {
|
||||||
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr);
|
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr);
|
||||||
else
|
} else {
|
||||||
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr);
|
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ioOp.empty()) {
|
if (ioOp.empty()) {
|
||||||
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
||||||
diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena");
|
diag.AddString("Unable to use type '"s.append(templateType.getAsString()).append("' with Athena"));
|
||||||
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +509,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false);
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false);
|
||||||
} else if (tsDecl->getName() == "Buffer") {
|
} else if (tsDecl->getName() == "Buffer") {
|
||||||
const clang::Expr* sizeExpr = nullptr;
|
const clang::Expr* sizeExpr = nullptr;
|
||||||
std::string sizeExprStr;
|
std::string sizeExprStr;
|
||||||
|
@ -514,8 +541,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
|
std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
|
||||||
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false);
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false);
|
|
||||||
} else if (tsDecl->getName() == "String") {
|
} else if (tsDecl->getName() == "String") {
|
||||||
std::string sizeExprStr;
|
std::string sizeExprStr;
|
||||||
for (const clang::TemplateArgument& arg : *tsType) {
|
for (const clang::TemplateArgument& arg : *tsType) {
|
||||||
|
@ -537,12 +563,13 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ioOp;
|
std::string ioOp;
|
||||||
if (!sizeExprStr.empty())
|
if (!sizeExprStr.empty()) {
|
||||||
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
|
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
|
||||||
else
|
} else {
|
||||||
ioOp = GetOpString(fieldName, propIdExpr);
|
ioOp = GetOpString(fieldName, propIdExpr);
|
||||||
|
}
|
||||||
|
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false);
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false);
|
||||||
} else if (tsDecl->getName() == "WString") {
|
} else if (tsDecl->getName() == "WString") {
|
||||||
llvm::APSInt endian(64, -1);
|
llvm::APSInt endian(64, -1);
|
||||||
std::string endianExprStr;
|
std::string endianExprStr;
|
||||||
|
@ -585,22 +612,24 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
|
|
||||||
std::string ioOp;
|
std::string ioOp;
|
||||||
if (!sizeExprStr.empty()) {
|
if (!sizeExprStr.empty()) {
|
||||||
if (defaultEndian)
|
if (defaultEndian) {
|
||||||
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
|
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr);
|
||||||
else
|
|
||||||
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr);
|
|
||||||
} else {
|
} else {
|
||||||
if (defaultEndian)
|
ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (defaultEndian) {
|
||||||
ioOp = GetOpString(fieldName, propIdExpr);
|
ioOp = GetOpString(fieldName, propIdExpr);
|
||||||
else
|
} else {
|
||||||
ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
|
ioOp = GetOpString(fieldName, propIdExpr, endianExprStr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, ioOp, false);
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false);
|
||||||
} else if (tsDecl->getName() == "Seek") {
|
} else if (tsDecl->getName() == "Seek") {
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
std::string offsetExprStr;
|
std::string offsetExprStr;
|
||||||
llvm::APSInt direction(64, 0);
|
llvm::APSInt direction(64, false);
|
||||||
const clang::Expr* directionExpr = nullptr;
|
const clang::Expr* directionExpr = nullptr;
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
for (const clang::TemplateArgument& arg : *tsType) {
|
for (const clang::TemplateArgument& arg : *tsType) {
|
||||||
|
@ -620,8 +649,11 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
offsetExprStr = offsetLiteral.toString(10);
|
offsetExprStr = offsetLiteral.toString(10);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
clang::APValue result;
|
||||||
|
if (expr->isCXX11ConstantExpr(context, &result)) {
|
||||||
directionExpr = expr;
|
directionExpr = expr;
|
||||||
if (!expr->isIntegerConstantExpr(direction, context)) {
|
direction = result.getInt();
|
||||||
|
} else {
|
||||||
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getExprLoc(), AthenaError);
|
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getExprLoc(), AthenaError);
|
||||||
diag.AddString("Unable to use non-constant direction expression in Athena");
|
diag.AddString("Unable to use non-constant direction expression in Athena");
|
||||||
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
|
diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true));
|
||||||
|
@ -650,15 +682,16 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directionVal == 0)
|
if (directionVal == 0) {
|
||||||
outputNodes.emplace_back(NodeType::DoSeek, fieldName, "<Op>("s + offsetExprStr + ", athena::Begin, s)",
|
outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName),
|
||||||
false);
|
"<Op>("s.append(offsetExprStr).append(", athena::SeekOrigin::Begin, s)"), false);
|
||||||
else if (directionVal == 1)
|
} else if (directionVal == 1) {
|
||||||
outputNodes.emplace_back(NodeType::DoSeek, fieldName, "<Op>("s + offsetExprStr + ", athena::Current, s)",
|
outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName),
|
||||||
false);
|
"<Op>("s.append(offsetExprStr).append(", athena::SeekOrigin::Current, s)"), false);
|
||||||
else if (directionVal == 2)
|
} else if (directionVal == 2) {
|
||||||
outputNodes.emplace_back(NodeType::DoSeek, fieldName, "<Op>("s + offsetExprStr + ", athena::End, s)",
|
outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName),
|
||||||
false);
|
"<Op>("s.append(offsetExprStr).append(", athena::SeekOrigin::End, s)"), false);
|
||||||
|
}
|
||||||
} else if (tsDecl->getName() == "Align") {
|
} else if (tsDecl->getName() == "Align") {
|
||||||
llvm::APSInt align(64, 0);
|
llvm::APSInt align(64, 0);
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
|
@ -677,25 +710,26 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
if (bad)
|
if (bad)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int64_t alignVal = align.getSExtValue();
|
const int64_t alignVal = align.getSExtValue();
|
||||||
if (alignVal) {
|
if (alignVal) {
|
||||||
outputNodes.emplace_back(NodeType::DoAlign, fieldName, "<Op>("s + align.toString(10, true) + ", s)", false);
|
outputNodes.emplace_back(NodeType::DoAlign, std::move(fieldName),
|
||||||
|
"<Op>("s.append(align.toString(10, true)).append(", s)"), false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const clang::NamedDecl* nd = tsDecl->getTemplatedDecl();
|
const clang::NamedDecl* nd = tsDecl->getTemplatedDecl();
|
||||||
if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null<clang::CXXRecordDecl>(nd)) {
|
if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null<clang::CXXRecordDecl>(nd)) {
|
||||||
std::string baseDNA;
|
std::string baseDNA2;
|
||||||
if (isDNARecord(rd, baseDNA))
|
if (isDNARecord(rd, baseDNA2)) {
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false);
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), GetOpString(fieldName, propIdExpr), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (regType->getTypeClass() == clang::Type::Record) {
|
||||||
else if (regType->getTypeClass() == clang::Type::Record) {
|
|
||||||
const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl();
|
const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl();
|
||||||
std::string baseDNA;
|
std::string baseDNA2;
|
||||||
if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA))
|
if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) {
|
||||||
outputNodes.emplace_back(NodeType::Do, fieldName, GetOpString(fieldName, propIdExpr), false);
|
outputNodes.emplace_back(NodeType::Do, std::move(fieldName), GetOpString(fieldName, propIdExpr), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,7 +815,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ioOp;
|
std::string ioOp;
|
||||||
bool isDNAType = false;
|
|
||||||
for (const clang::TemplateArgument& arg : *tsType) {
|
for (const clang::TemplateArgument& arg : *tsType) {
|
||||||
if (arg.getKind() == clang::TemplateArgument::Type) {
|
if (arg.getKind() == clang::TemplateArgument::Type) {
|
||||||
if (defaultEndian)
|
if (defaultEndian)
|
||||||
|
@ -793,7 +826,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
|
|
||||||
if (ioOp.empty()) {
|
if (ioOp.empty()) {
|
||||||
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
||||||
diag.AddString("Unable to use type '" + tsDecl->getName().str() + "' with Athena");
|
diag.AddString("Unable to use type '"s.append(tsDecl->getName().str()).append("' with Athena"));
|
||||||
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -841,7 +874,6 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
|
|
||||||
clang::QualType templateType;
|
clang::QualType templateType;
|
||||||
std::string ioOp;
|
std::string ioOp;
|
||||||
bool isDNAType = false;
|
|
||||||
for (const clang::TemplateArgument& arg : *tsType) {
|
for (const clang::TemplateArgument& arg : *tsType) {
|
||||||
if (arg.getKind() == clang::TemplateArgument::Type) {
|
if (arg.getKind() == clang::TemplateArgument::Type) {
|
||||||
templateType = arg.getAsType().getCanonicalType();
|
templateType = arg.getAsType().getCanonicalType();
|
||||||
|
@ -854,7 +886,7 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
|
|
||||||
if (ioOp.empty()) {
|
if (ioOp.empty()) {
|
||||||
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError);
|
||||||
diag.AddString("Unable to use type '" + templateType.getAsString() + "' with Athena");
|
diag.AddString("Unable to use type '"s.append(templateType.getAsString()).append("' with Athena"));
|
||||||
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -992,20 +1024,18 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor> {
|
||||||
} else {
|
} else {
|
||||||
const clang::NamedDecl* nd = tsDecl->getTemplatedDecl();
|
const clang::NamedDecl* nd = tsDecl->getTemplatedDecl();
|
||||||
if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null<clang::CXXRecordDecl>(nd)) {
|
if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null<clang::CXXRecordDecl>(nd)) {
|
||||||
std::string baseDNA;
|
std::string baseDNA2;
|
||||||
if (isDNARecord(rd, baseDNA)) {
|
if (isDNARecord(rd, baseDNA2)) {
|
||||||
fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n"
|
fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n"
|
||||||
<< " Do" << GetOpString(fieldName, propIdExpr) << ";\n"
|
<< " Do" << GetOpString(fieldName, propIdExpr) << ";\n"
|
||||||
<< " return true;\n";
|
<< " return true;\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (regType->getTypeClass() == clang::Type::Record) {
|
||||||
|
|
||||||
else if (regType->getTypeClass() == clang::Type::Record) {
|
|
||||||
const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl();
|
const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl();
|
||||||
std::string baseDNA;
|
std::string baseDNA2;
|
||||||
if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA)) {
|
if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) {
|
||||||
fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n"
|
fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n"
|
||||||
<< " Do" << GetOpString(fieldName, propIdExpr) << ";\n"
|
<< " Do" << GetOpString(fieldName, propIdExpr) << ";\n"
|
||||||
<< " return true;\n";
|
<< " return true;\n";
|
||||||
|
@ -1167,7 +1197,8 @@ int main(int argc, const char** argv) {
|
||||||
if (Help)
|
if (Help)
|
||||||
llvm::cl::PrintHelpMessage();
|
llvm::cl::PrintHelpMessage();
|
||||||
|
|
||||||
std::vector<std::string> args = {"clang-tool",
|
std::vector<std::string> args = {
|
||||||
|
"clang-tool",
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
"--gcc-toolchain=/usr",
|
"--gcc-toolchain=/usr",
|
||||||
#endif
|
#endif
|
||||||
|
@ -1178,13 +1209,15 @@ int main(int argc, const char** argv) {
|
||||||
"-Wno-nullability-completeness",
|
"-Wno-nullability-completeness",
|
||||||
"-Werror=shadow-field",
|
"-Werror=shadow-field",
|
||||||
"-I" XSTR(INSTALL_PREFIX) "/lib/clang/" CLANG_VERSION_STRING "/include",
|
"-I" XSTR(INSTALL_PREFIX) "/lib/clang/" CLANG_VERSION_STRING "/include",
|
||||||
"-I" XSTR(INSTALL_PREFIX) "/include/Athena"};
|
"-I" XSTR(INSTALL_PREFIX) "/include/Athena",
|
||||||
for (int a = 1; a < argc; ++a)
|
};
|
||||||
args.push_back(argv[a]);
|
for (int a = 1; a < argc; ++a) {
|
||||||
|
args.emplace_back(argv[a]);
|
||||||
|
}
|
||||||
|
|
||||||
llvm::IntrusiveRefCntPtr<clang::FileManager> fman(new clang::FileManager(clang::FileSystemOptions()));
|
llvm::IntrusiveRefCntPtr<clang::FileManager> fman(new clang::FileManager(clang::FileSystemOptions()));
|
||||||
ATDNAAction* action = new ATDNAAction();
|
ATDNAAction* action = new ATDNAAction();
|
||||||
clang::tooling::ToolInvocation TI(args, action, fman.get());
|
clang::tooling::ToolInvocation TI(std::move(args), action, fman.get());
|
||||||
if (!TI.run())
|
if (!TI.run())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <athena/DNAYaml.hpp>
|
#include <athena/DNAYaml.hpp>
|
||||||
|
|
||||||
using namespace athena;
|
using namespace athena;
|
||||||
typedef io::DNA<Big> BigDNA;
|
typedef io::DNA<Endian::Big> BigDNA;
|
||||||
|
|
||||||
enum ETest : atUint8 { ZERO, ONE, TWO, THREE };
|
enum ETest : atUint8 { ZERO, ONE, TWO, THREE };
|
||||||
|
|
||||||
|
@ -54,13 +54,13 @@ struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) TESTFile : p
|
||||||
Value<TESTTemplateSubFile<atInt32, 36>> nestedTemplate1;
|
Value<TESTTemplateSubFile<atInt32, 36>> nestedTemplate1;
|
||||||
Value<TESTTemplateSubFile<atInt64, 96>> nestedTemplate2;
|
Value<TESTTemplateSubFile<atInt64, 96>> nestedTemplate2;
|
||||||
|
|
||||||
Value<atUint32, Little> arrCount[2];
|
Value<atUint32, Endian::Little> arrCount[2];
|
||||||
Vector<atUint32, AT_DNA_COUNT(arrCount[0])> array;
|
Vector<atUint32, AT_DNA_COUNT(arrCount[0])> array;
|
||||||
|
|
||||||
Value<atUint32> arrAltCount;
|
Value<atUint32> arrAltCount;
|
||||||
Vector<atUint32, AT_DNA_COUNT(arrAltCount)> arrayAlt;
|
Vector<atUint32, AT_DNA_COUNT(arrAltCount)> arrayAlt;
|
||||||
|
|
||||||
Seek<21, Current> seek;
|
Seek<21, SeekOrigin::Current> seek;
|
||||||
|
|
||||||
Value<atUint32> arrCount2;
|
Value<atUint32> arrCount2;
|
||||||
Vector<TESTSubFile<ETest::ZERO>, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2;
|
Vector<TESTSubFile<ETest::ZERO>, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2;
|
||||||
|
|
|
@ -372,7 +372,7 @@ struct Read {
|
||||||
}
|
}
|
||||||
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) { r.seek(amount, whence); }
|
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) { r.seek(amount, whence); }
|
||||||
static void DoAlign(atInt64 amount, StreamT& r) {
|
static void DoAlign(atInt64 amount, StreamT& r) {
|
||||||
r.seek((r.position() + amount - 1) / amount * amount, athena::Begin);
|
r.seek((r.position() + amount - 1) / amount * amount, athena::SeekOrigin::Begin);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#define __READ_S(type, endian) \
|
#define __READ_S(type, endian) \
|
||||||
|
@ -1148,29 +1148,29 @@ void __BinarySizeProp64(const T& obj, size_t& s) {
|
||||||
#define AT_SUBSPECIALIZE_DNA(...) \
|
#define AT_SUBSPECIALIZE_DNA(...) \
|
||||||
template <> \
|
template <> \
|
||||||
template <> \
|
template <> \
|
||||||
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::BinarySize>(typename BinarySize::StreamT & s) { \
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::BinarySize>(typename BinarySize::StreamT & s) { \
|
||||||
_binarySize(s); \
|
_binarySize(s); \
|
||||||
} \
|
} \
|
||||||
template <> \
|
template <> \
|
||||||
template <> \
|
template <> \
|
||||||
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::Read>(typename Read::StreamT & r) { \
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::Read>(typename Read::StreamT & r) { \
|
||||||
_read(r); \
|
_read(r); \
|
||||||
} \
|
} \
|
||||||
template <> \
|
template <> \
|
||||||
template <> \
|
template <> \
|
||||||
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::Write>(typename Write::StreamT & w) { \
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::Write>(typename Write::StreamT & w) { \
|
||||||
_write(w); \
|
_write(w); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AT_SUBSPECIALIZE_DNA_YAML(...) \
|
#define AT_SUBSPECIALIZE_DNA_YAML(...) \
|
||||||
template <> \
|
template <> \
|
||||||
template <> \
|
template <> \
|
||||||
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::ReadYaml>(typename ReadYaml::StreamT & r) { \
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::ReadYaml>(typename ReadYaml::StreamT & r) { \
|
||||||
_read(r); \
|
_read(r); \
|
||||||
} \
|
} \
|
||||||
template <> \
|
template <> \
|
||||||
template <> \
|
template <> \
|
||||||
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::WriteYaml>(typename WriteYaml::StreamT & w) { \
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::WriteYaml>(typename WriteYaml::StreamT & w) { \
|
||||||
_write(w); \
|
_write(w); \
|
||||||
} \
|
} \
|
||||||
AT_SUBSPECIALIZE_DNA(__VA_ARGS__)
|
AT_SUBSPECIALIZE_DNA(__VA_ARGS__)
|
||||||
|
|
|
@ -116,7 +116,7 @@ bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) {
|
||||||
atUint64 pos = fin.position();
|
atUint64 pos = fin.position();
|
||||||
yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)YAMLAthenaReader, &fin);
|
yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)YAMLAthenaReader, &fin);
|
||||||
bool retval = reader.ValidateClassType(DNASubtype::DNAType());
|
bool retval = reader.ValidateClassType(DNASubtype::DNAType());
|
||||||
fin.seek(pos, athena::Begin);
|
fin.seek(pos, athena::SeekOrigin::Begin);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,33 +87,33 @@ typedef struct stat64 atStat64_t;
|
||||||
|
|
||||||
#ifndef ENABLE_BITWISE_ENUM
|
#ifndef ENABLE_BITWISE_ENUM
|
||||||
#define ENABLE_BITWISE_ENUM(type) \
|
#define ENABLE_BITWISE_ENUM(type) \
|
||||||
constexpr type operator|(type a, type b) { \
|
constexpr type operator|(type a, type b) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
return type(static_cast<T>(a) | static_cast<T>(b)); \
|
return type(static_cast<T>(a) | static_cast<T>(b)); \
|
||||||
} \
|
} \
|
||||||
constexpr type operator&(type a, type b) { \
|
constexpr type operator&(type a, type b) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
return type(static_cast<T>(a) & static_cast<T>(b)); \
|
return type(static_cast<T>(a) & static_cast<T>(b)); \
|
||||||
} \
|
} \
|
||||||
inline type& operator|=(type& a, const type& b) { \
|
constexpr type& operator|=(type& a, type b) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
a = type(static_cast<T>(a) | static_cast<T>(b)); \
|
a = type(static_cast<T>(a) | static_cast<T>(b)); \
|
||||||
return a; \
|
return a; \
|
||||||
} \
|
} \
|
||||||
inline type& operator&=(type& a, const type& b) { \
|
constexpr type& operator&=(type& a, type b) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
a = type(static_cast<T>(a) & static_cast<T>(b)); \
|
a = type(static_cast<T>(a) & static_cast<T>(b)); \
|
||||||
return a; \
|
return a; \
|
||||||
} \
|
} \
|
||||||
constexpr type operator~(type key) { \
|
constexpr type operator~(type key) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
return type(~static_cast<T>(key)); \
|
return type(~static_cast<T>(key)); \
|
||||||
} \
|
} \
|
||||||
constexpr bool True(type key) { \
|
constexpr bool True(type key) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
return static_cast<T>(key) != 0; \
|
return static_cast<T>(key) != 0; \
|
||||||
} \
|
} \
|
||||||
constexpr bool False(type key) { \
|
constexpr bool False(type key) noexcept { \
|
||||||
using T = std::underlying_type_t<type>; \
|
using T = std::underlying_type_t<type>; \
|
||||||
return static_cast<T>(key) == 0; \
|
return static_cast<T>(key) == 0; \
|
||||||
}
|
}
|
||||||
|
@ -123,9 +123,9 @@ namespace athena {
|
||||||
namespace error {
|
namespace error {
|
||||||
enum class Level { Message, Warning, Error, Fatal };
|
enum class Level { Message, Warning, Error, Fatal };
|
||||||
}
|
}
|
||||||
enum SeekOrigin { Begin, Current, End };
|
enum class SeekOrigin { Begin, Current, End };
|
||||||
|
|
||||||
enum Endian { Little, Big };
|
enum class Endian { Little, Big };
|
||||||
|
|
||||||
namespace io {
|
namespace io {
|
||||||
template <Endian DNAE>
|
template <Endian DNAE>
|
||||||
|
|
|
@ -23,9 +23,9 @@ protected:
|
||||||
void setError() { m_hasError = true; }
|
void setError() { m_hasError = true; }
|
||||||
bool m_hasError = false;
|
bool m_hasError = false;
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
Endian m_endian = Big;
|
Endian m_endian = Endian::Big;
|
||||||
#else
|
#else
|
||||||
Endian m_endian = Little;
|
Endian m_endian = Endian::Little;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
} // namespace athena::io
|
} // namespace athena::io
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
atInt16 readInt16() {
|
atInt16 readInt16() {
|
||||||
atInt16 val = 0;
|
atInt16 val = 0;
|
||||||
readUBytesToBuf(&val, 2);
|
readUBytesToBuf(&val, 2);
|
||||||
return m_endian == Big ? utility::BigInt16(val) : utility::LittleInt16(val);
|
return m_endian == Endian::Big ? utility::BigInt16(val) : utility::LittleInt16(val);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
atInt16 readVal(std::enable_if_t<std::is_same_v<T, atInt16>>* = nullptr) {
|
atInt16 readVal(std::enable_if_t<std::is_same_v<T, atInt16>>* = nullptr) {
|
||||||
|
@ -229,7 +229,7 @@ public:
|
||||||
atInt32 readInt32() {
|
atInt32 readInt32() {
|
||||||
atInt32 val = 0;
|
atInt32 val = 0;
|
||||||
readUBytesToBuf(&val, 4);
|
readUBytesToBuf(&val, 4);
|
||||||
return m_endian == Big ? utility::BigInt32(val) : utility::LittleInt32(val);
|
return m_endian == Endian::Big ? utility::BigInt32(val) : utility::LittleInt32(val);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
atInt32 readVal(std::enable_if_t<std::is_same_v<T, atInt32>>* = nullptr) {
|
atInt32 readVal(std::enable_if_t<std::is_same_v<T, atInt32>>* = nullptr) {
|
||||||
|
@ -315,7 +315,7 @@ public:
|
||||||
atInt64 readInt64() {
|
atInt64 readInt64() {
|
||||||
atInt64 val = 0;
|
atInt64 val = 0;
|
||||||
readUBytesToBuf(&val, 8);
|
readUBytesToBuf(&val, 8);
|
||||||
return m_endian == Big ? utility::BigInt64(val) : utility::LittleInt64(val);
|
return m_endian == Endian::Big ? utility::BigInt64(val) : utility::LittleInt64(val);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
atInt64 readVal(std::enable_if_t<std::is_same_v<T, atInt64>>* = nullptr) {
|
atInt64 readVal(std::enable_if_t<std::is_same_v<T, atInt64>>* = nullptr) {
|
||||||
|
@ -401,7 +401,7 @@ public:
|
||||||
float readFloat() {
|
float readFloat() {
|
||||||
float val = 0.f;
|
float val = 0.f;
|
||||||
readUBytesToBuf(&val, 4);
|
readUBytesToBuf(&val, 4);
|
||||||
return m_endian == Big ? utility::BigFloat(val) : utility::LittleFloat(val);
|
return m_endian == Endian::Big ? utility::BigFloat(val) : utility::LittleFloat(val);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
float readVal(std::enable_if_t<std::is_same_v<T, float>>* = nullptr) {
|
float readVal(std::enable_if_t<std::is_same_v<T, float>>* = nullptr) {
|
||||||
|
@ -446,7 +446,7 @@ public:
|
||||||
double readDouble() {
|
double readDouble() {
|
||||||
double val = 0.0;
|
double val = 0.0;
|
||||||
readUBytesToBuf(&val, 8);
|
readUBytesToBuf(&val, 8);
|
||||||
return m_endian == Big ? utility::BigDouble(val) : utility::LittleDouble(val);
|
return m_endian == Endian::Big ? utility::BigDouble(val) : utility::LittleDouble(val);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
double readVal(std::enable_if_t<std::is_same_v<T, double>>* = nullptr) {
|
double readVal(std::enable_if_t<std::is_same_v<T, double>>* = nullptr) {
|
||||||
|
@ -513,7 +513,7 @@ public:
|
||||||
atVec2f readVec2f() {
|
atVec2f readVec2f() {
|
||||||
simd_floats val = {};
|
simd_floats val = {};
|
||||||
readUBytesToBuf(val.data(), 8);
|
readUBytesToBuf(val.data(), 8);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
val[0] = utility::BigFloat(val[0]);
|
val[0] = utility::BigFloat(val[0]);
|
||||||
val[1] = utility::BigFloat(val[1]);
|
val[1] = utility::BigFloat(val[1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -581,7 +581,7 @@ public:
|
||||||
atVec3f readVec3f() {
|
atVec3f readVec3f() {
|
||||||
simd_floats val = {};
|
simd_floats val = {};
|
||||||
readUBytesToBuf(val.data(), 12);
|
readUBytesToBuf(val.data(), 12);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
val[0] = utility::BigFloat(val[0]);
|
val[0] = utility::BigFloat(val[0]);
|
||||||
val[1] = utility::BigFloat(val[1]);
|
val[1] = utility::BigFloat(val[1]);
|
||||||
val[2] = utility::BigFloat(val[2]);
|
val[2] = utility::BigFloat(val[2]);
|
||||||
|
@ -650,7 +650,7 @@ public:
|
||||||
atVec4f readVec4f() {
|
atVec4f readVec4f() {
|
||||||
simd_floats val = {};
|
simd_floats val = {};
|
||||||
readUBytesToBuf(val.data(), 16);
|
readUBytesToBuf(val.data(), 16);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
val[0] = utility::BigFloat(val[0]);
|
val[0] = utility::BigFloat(val[0]);
|
||||||
val[1] = utility::BigFloat(val[1]);
|
val[1] = utility::BigFloat(val[1]);
|
||||||
val[2] = utility::BigFloat(val[2]);
|
val[2] = utility::BigFloat(val[2]);
|
||||||
|
@ -720,7 +720,7 @@ public:
|
||||||
atVec2d readVec2d() {
|
atVec2d readVec2d() {
|
||||||
simd_doubles val = {};
|
simd_doubles val = {};
|
||||||
readUBytesToBuf(val.data(), 16);
|
readUBytesToBuf(val.data(), 16);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
val[0] = utility::BigDouble(val[0]);
|
val[0] = utility::BigDouble(val[0]);
|
||||||
val[1] = utility::BigDouble(val[1]);
|
val[1] = utility::BigDouble(val[1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -788,7 +788,7 @@ public:
|
||||||
atVec3d readVec3d() {
|
atVec3d readVec3d() {
|
||||||
simd_doubles val = {};
|
simd_doubles val = {};
|
||||||
readUBytesToBuf(val.data(), 24);
|
readUBytesToBuf(val.data(), 24);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
val[0] = utility::BigDouble(val[0]);
|
val[0] = utility::BigDouble(val[0]);
|
||||||
val[1] = utility::BigDouble(val[1]);
|
val[1] = utility::BigDouble(val[1]);
|
||||||
val[2] = utility::BigDouble(val[2]);
|
val[2] = utility::BigDouble(val[2]);
|
||||||
|
@ -857,7 +857,7 @@ public:
|
||||||
atVec4d readVec4d() {
|
atVec4d readVec4d() {
|
||||||
simd_doubles val = {};
|
simd_doubles val = {};
|
||||||
readUBytesToBuf(val.data(), 32);
|
readUBytesToBuf(val.data(), 32);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
val[0] = utility::BigDouble(val[0]);
|
val[0] = utility::BigDouble(val[0]);
|
||||||
val[1] = utility::BigDouble(val[1]);
|
val[1] = utility::BigDouble(val[1]);
|
||||||
val[2] = utility::BigDouble(val[2]);
|
val[2] = utility::BigDouble(val[2]);
|
||||||
|
|
|
@ -91,10 +91,11 @@ public:
|
||||||
* @param val The value to write to the buffer
|
* @param val The value to write to the buffer
|
||||||
*/
|
*/
|
||||||
void writeInt16(atInt16 val) {
|
void writeInt16(atInt16 val) {
|
||||||
if (m_endian == Big)
|
if (m_endian == Endian::Big) {
|
||||||
utility::BigInt16(val);
|
utility::BigInt16(val);
|
||||||
else
|
} else {
|
||||||
utility::LittleInt16(val);
|
utility::LittleInt16(val);
|
||||||
|
}
|
||||||
writeUBytes((atUint8*)&val, 2);
|
writeUBytes((atUint8*)&val, 2);
|
||||||
}
|
}
|
||||||
void writeVal(atInt16 val) { writeInt16(val); }
|
void writeVal(atInt16 val) { writeInt16(val); }
|
||||||
|
@ -151,10 +152,11 @@ public:
|
||||||
* @param val The value to write to the buffer
|
* @param val The value to write to the buffer
|
||||||
*/
|
*/
|
||||||
void writeInt32(atInt32 val) {
|
void writeInt32(atInt32 val) {
|
||||||
if (m_endian == Big)
|
if (m_endian == Endian::Big) {
|
||||||
utility::BigInt32(val);
|
utility::BigInt32(val);
|
||||||
else
|
} else {
|
||||||
utility::LittleInt32(val);
|
utility::LittleInt32(val);
|
||||||
|
}
|
||||||
writeUBytes((atUint8*)&val, 4);
|
writeUBytes((atUint8*)&val, 4);
|
||||||
}
|
}
|
||||||
void writeVal(atInt32 val) { writeInt32(val); }
|
void writeVal(atInt32 val) { writeInt32(val); }
|
||||||
|
@ -211,10 +213,11 @@ public:
|
||||||
* @param val The value to write to the buffer
|
* @param val The value to write to the buffer
|
||||||
*/
|
*/
|
||||||
void writeInt64(atInt64 val) {
|
void writeInt64(atInt64 val) {
|
||||||
if (m_endian == Big)
|
if (m_endian == Endian::Big) {
|
||||||
utility::BigInt64(val);
|
utility::BigInt64(val);
|
||||||
else
|
} else {
|
||||||
utility::LittleInt64(val);
|
utility::LittleInt64(val);
|
||||||
|
}
|
||||||
writeUBytes((atUint8*)&val, 8);
|
writeUBytes((atUint8*)&val, 8);
|
||||||
}
|
}
|
||||||
void writeVal(atInt64 val) { writeInt64(val); }
|
void writeVal(atInt64 val) { writeInt64(val); }
|
||||||
|
@ -271,10 +274,11 @@ public:
|
||||||
* @param val The value to write to the buffer
|
* @param val The value to write to the buffer
|
||||||
*/
|
*/
|
||||||
void writeFloat(float val) {
|
void writeFloat(float val) {
|
||||||
if (m_endian == Big)
|
if (m_endian == Endian::Big) {
|
||||||
val = utility::BigFloat(val);
|
val = utility::BigFloat(val);
|
||||||
else
|
} else {
|
||||||
val = utility::LittleFloat(val);
|
val = utility::LittleFloat(val);
|
||||||
|
}
|
||||||
writeUBytes((atUint8*)&val, 4);
|
writeUBytes((atUint8*)&val, 4);
|
||||||
}
|
}
|
||||||
void writeVal(float val) { writeFloat(val); }
|
void writeVal(float val) { writeFloat(val); }
|
||||||
|
@ -307,10 +311,11 @@ public:
|
||||||
* @param val The value to write to the buffer
|
* @param val The value to write to the buffer
|
||||||
*/
|
*/
|
||||||
void writeDouble(double val) {
|
void writeDouble(double val) {
|
||||||
if (m_endian == Big)
|
if (m_endian == Endian::Big) {
|
||||||
utility::BigDouble(val);
|
utility::BigDouble(val);
|
||||||
else
|
} else {
|
||||||
utility::LittleDouble(val);
|
utility::LittleDouble(val);
|
||||||
|
}
|
||||||
writeUBytes((atUint8*)&val, 8);
|
writeUBytes((atUint8*)&val, 8);
|
||||||
}
|
}
|
||||||
void writeVal(double val) { writeDouble(val); }
|
void writeVal(double val) { writeDouble(val); }
|
||||||
|
@ -354,7 +359,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void writeVec2f(const atVec2f& vec) {
|
void writeVec2f(const atVec2f& vec) {
|
||||||
simd_floats tmp(vec.simd);
|
simd_floats tmp(vec.simd);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
tmp[0] = utility::BigFloat(tmp[0]);
|
tmp[0] = utility::BigFloat(tmp[0]);
|
||||||
tmp[1] = utility::BigFloat(tmp[1]);
|
tmp[1] = utility::BigFloat(tmp[1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -398,7 +403,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void writeVec3f(const atVec3f& vec) {
|
void writeVec3f(const atVec3f& vec) {
|
||||||
simd_floats tmp(vec.simd);
|
simd_floats tmp(vec.simd);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
tmp[0] = utility::BigFloat(tmp[0]);
|
tmp[0] = utility::BigFloat(tmp[0]);
|
||||||
tmp[1] = utility::BigFloat(tmp[1]);
|
tmp[1] = utility::BigFloat(tmp[1]);
|
||||||
tmp[2] = utility::BigFloat(tmp[2]);
|
tmp[2] = utility::BigFloat(tmp[2]);
|
||||||
|
@ -446,7 +451,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void writeVec4f(const atVec4f& vec) {
|
void writeVec4f(const atVec4f& vec) {
|
||||||
simd_floats tmp(vec.simd);
|
simd_floats tmp(vec.simd);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
tmp[0] = utility::BigFloat(tmp[0]);
|
tmp[0] = utility::BigFloat(tmp[0]);
|
||||||
tmp[1] = utility::BigFloat(tmp[1]);
|
tmp[1] = utility::BigFloat(tmp[1]);
|
||||||
tmp[2] = utility::BigFloat(tmp[2]);
|
tmp[2] = utility::BigFloat(tmp[2]);
|
||||||
|
@ -498,7 +503,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void writeVec2d(const atVec2d& vec) {
|
void writeVec2d(const atVec2d& vec) {
|
||||||
simd_doubles tmp(vec.simd);
|
simd_doubles tmp(vec.simd);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
tmp[0] = utility::BigDouble(tmp[0]);
|
tmp[0] = utility::BigDouble(tmp[0]);
|
||||||
tmp[1] = utility::BigDouble(tmp[1]);
|
tmp[1] = utility::BigDouble(tmp[1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -542,7 +547,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void writeVec3d(const atVec3d& vec) {
|
void writeVec3d(const atVec3d& vec) {
|
||||||
simd_doubles tmp(vec.simd);
|
simd_doubles tmp(vec.simd);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
tmp[0] = utility::BigDouble(tmp[0]);
|
tmp[0] = utility::BigDouble(tmp[0]);
|
||||||
tmp[1] = utility::BigDouble(tmp[1]);
|
tmp[1] = utility::BigDouble(tmp[1]);
|
||||||
tmp[2] = utility::BigDouble(tmp[2]);
|
tmp[2] = utility::BigDouble(tmp[2]);
|
||||||
|
@ -590,7 +595,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void writeVec4d(const atVec4d& vec) {
|
void writeVec4d(const atVec4d& vec) {
|
||||||
simd_doubles tmp(vec.simd);
|
simd_doubles tmp(vec.simd);
|
||||||
if (m_endian == Big) {
|
if (m_endian == Endian::Big) {
|
||||||
tmp[0] = utility::BigDouble(tmp[0]);
|
tmp[0] = utility::BigDouble(tmp[0]);
|
||||||
tmp[1] = utility::BigDouble(tmp[1]);
|
tmp[1] = utility::BigDouble(tmp[1]);
|
||||||
tmp[2] = utility::BigDouble(tmp[2]);
|
tmp[2] = utility::BigDouble(tmp[2]);
|
||||||
|
|
|
@ -90,11 +90,11 @@ public:
|
||||||
void writeUBytes(const atUint8* data, atUint64 length) override;
|
void writeUBytes(const atUint8* data, atUint64 length) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MemoryWriter() {}
|
MemoryWriter() = default;
|
||||||
atUint8* m_data;
|
atUint8* m_data = nullptr;
|
||||||
atUint64 m_length;
|
atUint64 m_length = 0;
|
||||||
atUint64 m_position;
|
atUint64 m_position = 0;
|
||||||
bool m_bufferOwned;
|
bool m_bufferOwned = false;
|
||||||
std::string m_filepath; //!< Path to the target file
|
std::string m_filepath; //!< Path to the target file
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ constexpr bool isSystemBigEndian() { return false; }
|
||||||
#else
|
#else
|
||||||
constexpr bool isSystemBigEndian() { return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; }
|
constexpr bool isSystemBigEndian() { return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; }
|
||||||
#endif
|
#endif
|
||||||
constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? Big : Little;
|
constexpr ::athena::Endian SystemEndian = isSystemBigEndian() ? ::athena::Endian::Big : ::athena::Endian::Little;
|
||||||
constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? Little : Big;
|
constexpr ::athena::Endian NotSystemEndian = isSystemBigEndian() ? ::athena::Endian::Little : ::athena::Endian::Big;
|
||||||
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
#define BSWAP_CONSTEXPR inline
|
#define BSWAP_CONSTEXPR inline
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#include "LZ77/LZLookupTable.hpp"
|
|
||||||
#include "LZ77/LZType10.hpp"
|
#include "LZ77/LZType10.hpp"
|
||||||
#include <athena/MemoryWriter.hpp>
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "LZ77/LZLookupTable.hpp"
|
||||||
|
|
||||||
|
#include <athena/MemoryWriter.hpp>
|
||||||
|
|
||||||
LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize)
|
LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize)
|
||||||
: LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) {
|
: LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) {
|
||||||
|
@ -17,25 +22,25 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe
|
||||||
athena::io::MemoryCopyWriter outbuf("tmp");
|
athena::io::MemoryCopyWriter outbuf("tmp");
|
||||||
outbuf.writeUint32(encodeSize);
|
outbuf.writeUint32(encodeSize);
|
||||||
|
|
||||||
atUint8* ptrStart = (atUint8*)src;
|
const atUint8* ptrStart = src;
|
||||||
atUint8* ptrEnd = (atUint8*)(src + srcLength);
|
const atUint8* ptrEnd = src + srcLength;
|
||||||
|
|
||||||
// At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be
|
// 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
|
// compressed it would take blockSize*2 bytes
|
||||||
atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written
|
auto compressedBytes = std::unique_ptr<atUint8[]>(new atUint8[m_blockSize * 2]); // Holds the compressed bytes yet to be written
|
||||||
|
|
||||||
while (ptrStart < ptrEnd) {
|
while (ptrStart < ptrEnd) {
|
||||||
atUint8 blockLen = 0;
|
atUint8 blockLen = 0;
|
||||||
// In Binary represents 1 if byte is compressed or 0 if not compressed
|
// 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
|
// For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed
|
||||||
atUint8* ptrBytes = compressedBytes;
|
atUint8* ptrBytes = compressedBytes.get();
|
||||||
|
|
||||||
for (atInt32 i = 0; i < m_blockSize; i++) {
|
for (atInt32 i = 0; i < m_blockSize; i++) {
|
||||||
// length_offset searchResult=Search(ptrStart, filedata, ptrEnd);
|
// length_offset searchResult=Search(ptrStart, filedata, ptrEnd);
|
||||||
LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
|
const LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
|
||||||
|
|
||||||
// If the number of bytes to be compressed is at least the size of the Minimum match
|
// If the number of bytes to be compressed is at least the size of the Minimum match
|
||||||
if (searchResult.length >= (atUint32)m_minMatch) {
|
if (searchResult.length >= static_cast<atUint32>(m_minMatch)) {
|
||||||
// Gotta swap the bytes since system is wii is big endian and most computers are little endian
|
// 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);
|
atUint16 lenOff = (((searchResult.length - m_minMatch) & 0xF) << 12) | ((searchResult.offset - 1) & 0xFFF);
|
||||||
athena::utility::BigUint16(lenOff);
|
athena::utility::BigUint16(lenOff);
|
||||||
|
@ -49,45 +54,50 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe
|
||||||
blockLen |= (1 << (7 - i));
|
blockLen |= (1 << (7 - i));
|
||||||
// Stores which of the next 8 bytes is compressed
|
// Stores which of the next 8 bytes is compressed
|
||||||
// bit 1 for compress and bit 0 for not compressed
|
// bit 1 for compress and bit 0 for not compressed
|
||||||
} else
|
} else {
|
||||||
*ptrBytes++ = *ptrStart++;
|
*ptrBytes++ = *ptrStart++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
outbuf.writeByte(blockLen);
|
outbuf.writeByte(blockLen);
|
||||||
outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
|
outbuf.writeUBytes(compressedBytes.get(), static_cast<atUint64>(ptrBytes - compressedBytes.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] compressedBytes;
|
|
||||||
compressedBytes = nullptr;
|
|
||||||
|
|
||||||
// Add zeros until the file is a multiple of 4
|
// Add zeros until the file is a multiple of 4
|
||||||
while ((outbuf.position() % 4) != 0)
|
while ((outbuf.position() % 4) != 0) {
|
||||||
outbuf.writeByte(0);
|
outbuf.writeByte(0);
|
||||||
|
}
|
||||||
|
|
||||||
*dstBuf = outbuf.data();
|
*dstBuf = outbuf.data();
|
||||||
outbuf.save();
|
outbuf.save();
|
||||||
return (atUint32)outbuf.length();
|
return static_cast<atUint32>(outbuf.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
|
atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
|
||||||
if (*(atUint8*)(src) != 0x10)
|
if (*src != 0x10) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
atUint32 uncompressedSize = *(atUint32*)(src); // Size of data when it is uncompressed
|
// Size of data when it is uncompressed
|
||||||
athena::utility::LittleUint32(uncompressedSize); // The compressed file has the filesize encoded in little endian
|
atUint32 uncompressedSize;
|
||||||
uncompressedSize = uncompressedSize >> 8; // first byte is the encode flag
|
std::memcpy(&uncompressedSize, src, sizeof(uncompressedSize));
|
||||||
|
|
||||||
atUint8* uncompressedData = new atUint8[uncompressedSize];
|
// The compressed file has the filesize encoded in little endian
|
||||||
atUint8* outputPtr = uncompressedData;
|
athena::utility::LittleUint32(uncompressedSize);
|
||||||
atUint8* outputEndPtr = uncompressedData + uncompressedSize;
|
|
||||||
atUint8* inputPtr = (atUint8*)src + 4;
|
// first byte is the encode flag
|
||||||
atUint8* inputEndPtr = (atUint8*)src + srcLength;
|
uncompressedSize = uncompressedSize >> 8;
|
||||||
|
|
||||||
|
auto uncompressedData = std::unique_ptr<atUint8[]>(new atUint8[uncompressedSize]);
|
||||||
|
atUint8* outputPtr = uncompressedData.get();
|
||||||
|
atUint8* outputEndPtr = uncompressedData.get() + uncompressedSize;
|
||||||
|
const atUint8* inputPtr = src + 4;
|
||||||
|
const atUint8* inputEndPtr = src + srcLength;
|
||||||
|
|
||||||
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
|
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
|
||||||
|
const atUint8 isCompressed = *inputPtr++;
|
||||||
|
|
||||||
atUint8 isCompressed = *inputPtr++;
|
for (atUint32 i = 0; i < static_cast<atUint32>(m_blockSize); i++) {
|
||||||
|
|
||||||
for (atUint32 i = 0; i < (atUint32)m_blockSize; i++) {
|
|
||||||
// Checks to see if the next byte is compressed by looking
|
// Checks to see if the next byte is compressed by looking
|
||||||
// at its binary representation - E.g 10010000
|
// at its binary representation - E.g 10010000
|
||||||
// This says that the first extracted byte and the four extracted byte is compressed
|
// This says that the first extracted byte and the four extracted byte is compressed
|
||||||
|
@ -101,28 +111,29 @@ atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLen
|
||||||
decoding.length = (lenOff >> 12) + m_minMatch;
|
decoding.length = (lenOff >> 12) + m_minMatch;
|
||||||
decoding.offset = static_cast<atUint16>((lenOff & 0xFFF) + 1);
|
decoding.offset = static_cast<atUint16>((lenOff & 0xFFF) + 1);
|
||||||
|
|
||||||
if ((outputPtr - decoding.offset) < uncompressedData) {
|
if ((outputPtr - decoding.offset) < uncompressedData.get()) {
|
||||||
// If the offset to look for uncompressed is passed the current uncompresed data then the data is not
|
// If the offset to look for uncompressed is passed the current uncompresed data then the data is not
|
||||||
// compressed
|
// compressed
|
||||||
delete[] uncompressedData;
|
|
||||||
uncompressedData = nullptr;
|
|
||||||
dst = nullptr;
|
dst = nullptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (atUint32 j = 0; j < decoding.length; ++j)
|
for (size_t j = 0; j < decoding.length; ++j) {
|
||||||
outputPtr[j] = (outputPtr - decoding.offset)[j];
|
outputPtr[j] = (outputPtr - decoding.offset)[j];
|
||||||
|
}
|
||||||
|
|
||||||
outputPtr += decoding.length;
|
outputPtr += decoding.length;
|
||||||
} else
|
} else {
|
||||||
*outputPtr++ = *inputPtr++;
|
*outputPtr++ = *inputPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr))
|
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*dst = uncompressedData;
|
*dst = uncompressedData.release();
|
||||||
|
|
||||||
return uncompressedSize;
|
return uncompressedSize;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#include "LZ77/LZLookupTable.hpp"
|
|
||||||
#include "LZ77/LZType11.hpp"
|
#include "LZ77/LZType11.hpp"
|
||||||
#include <athena/MemoryWriter.hpp>
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "LZ77/LZLookupTable.hpp"
|
||||||
|
|
||||||
|
#include <athena/MemoryWriter.hpp>
|
||||||
|
|
||||||
LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize)
|
LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize)
|
||||||
: LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) {
|
: LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) {
|
||||||
|
@ -12,32 +17,32 @@ LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimum
|
||||||
atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
|
atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
|
||||||
athena::io::MemoryCopyWriter outbuff("tmp");
|
athena::io::MemoryCopyWriter outbuff("tmp");
|
||||||
|
|
||||||
if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs
|
if (srcLength > 0xFFFFFF) { // If length is greater than 24 bits or 16 Megs
|
||||||
{
|
|
||||||
atUint32 encodeFlag = 0x11;
|
atUint32 encodeFlag = 0x11;
|
||||||
athena::utility::LittleUint32(encodeFlag);
|
athena::utility::LittleUint32(encodeFlag);
|
||||||
athena::utility::LittleUint32(srcLength); // Filesize data is little endian
|
athena::utility::LittleUint32(srcLength); // Filesize data is little endian
|
||||||
outbuff.writeUint32(encodeFlag);
|
outbuff.writeUint32(encodeFlag);
|
||||||
outbuff.writeUint32(srcLength);
|
outbuff.writeUint32(srcLength);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
atUint32 encodeSize = (srcLength << 8) | (0x11);
|
atUint32 encodeSize = (srcLength << 8) | (0x11);
|
||||||
athena::utility::LittleUint32(encodeSize);
|
athena::utility::LittleUint32(encodeSize);
|
||||||
outbuff.writeUint32(encodeSize);
|
outbuff.writeUint32(encodeSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
atUint8* ptrStart = (atUint8*)src;
|
const atUint8* ptrStart = src;
|
||||||
atUint8* ptrEnd = (atUint8*)(src + srcLength);
|
const atUint8* ptrEnd = src + srcLength;
|
||||||
|
|
||||||
// At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be
|
// 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
|
// 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;
|
// Holds the compressed bytes yet to be written
|
||||||
atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1
|
auto compressedBytes = std::unique_ptr<atUint8[]>(new atUint8[m_blockSize * 2]);
|
||||||
atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch;
|
|
||||||
atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1
|
const atUint8 maxTwoByteMatch = 0xF + 1;
|
||||||
atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch;
|
const atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1
|
||||||
|
const atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch;
|
||||||
|
const atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1
|
||||||
|
const atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15.
|
Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15.
|
||||||
|
@ -57,14 +62,14 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt
|
||||||
atUint8 blockSize = 0;
|
atUint8 blockSize = 0;
|
||||||
// In Binary represents 1 if byte is compressed or 0 if not compressed
|
// 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
|
// For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed
|
||||||
atUint8* ptrBytes = compressedBytes;
|
atUint8* ptrBytes = compressedBytes.get();
|
||||||
|
|
||||||
for (atInt32 i = 0; i < m_blockSize; i++) {
|
for (atInt32 i = 0; i < m_blockSize; i++) {
|
||||||
// length_offset searchResult=Search(filedata,ptrStart,ptrEnd);
|
// length_offset searchResult=Search(filedata,ptrStart,ptrEnd);
|
||||||
LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
|
const LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd);
|
||||||
|
|
||||||
// If the number of bytes to be compressed is at least the size of the Minimum match
|
// If the number of bytes to be compressed is at least the size of the Minimum match
|
||||||
if (searchResult.length >= (atUint32)m_minMatch) {
|
if (searchResult.length >= static_cast<atUint32>(m_minMatch)) {
|
||||||
// Gotta swap the bytes since system is wii is big endian and most computers are little endian
|
// Gotta swap the bytes since system is wii is big endian and most computers are little endian
|
||||||
|
|
||||||
if (searchResult.length <= maxTwoByteMatch) {
|
if (searchResult.length <= maxTwoByteMatch) {
|
||||||
|
@ -79,10 +84,10 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt
|
||||||
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
|
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
|
||||||
);
|
);
|
||||||
athena::utility::BigUint32(lenOff);
|
athena::utility::BigUint32(lenOff);
|
||||||
memcpy(ptrBytes, (atUint8*)&lenOff + 1,
|
memcpy(ptrBytes, reinterpret_cast<atUint8*>(&lenOff) + 1,
|
||||||
3); // Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456
|
3); // Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456
|
||||||
ptrBytes += 3;
|
ptrBytes += 3;
|
||||||
} else if (searchResult.length <= (atUint32)maxFourByteMatch) {
|
} else if (searchResult.length <= static_cast<atUint32>(maxFourByteMatch)) {
|
||||||
atUint32 lenOff = ((1 << 28) | // Bits 31-28 Flag to say that this is four bytes
|
atUint32 lenOff = ((1 << 28) | // Bits 31-28 Flag to say that this is four bytes
|
||||||
(((searchResult.length - minFourByteMatch) & 0xFFFF) << 12) | // Bits 28-12
|
(((searchResult.length - minFourByteMatch) & 0xFFFF) << 12) | // Bits 28-12
|
||||||
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
|
((searchResult.offset - 1) & 0xFFF) // Bits 11-0
|
||||||
|
@ -97,83 +102,80 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt
|
||||||
blockSize |= (1 << (7 - i));
|
blockSize |= (1 << (7 - i));
|
||||||
// Stores which of the next 8 bytes is compressed
|
// Stores which of the next 8 bytes is compressed
|
||||||
// bit 1 for compress and bit 0 for not compressed
|
// bit 1 for compress and bit 0 for not compressed
|
||||||
} else
|
} else {
|
||||||
*ptrBytes++ = *ptrStart++;
|
*ptrBytes++ = *ptrStart++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
outbuff.writeByte(blockSize);
|
outbuff.writeByte(blockSize);
|
||||||
outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes));
|
outbuff.writeUBytes(compressedBytes.get(), static_cast<atUint64>(ptrBytes - compressedBytes.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] compressedBytes;
|
|
||||||
compressedBytes = nullptr;
|
|
||||||
|
|
||||||
// Add zeros until the file is a multiple of 4
|
// Add zeros until the file is a multiple of 4
|
||||||
while ((outbuff.position() % 4) != 0)
|
while ((outbuff.position() % 4) != 0) {
|
||||||
outbuff.writeByte(0);
|
outbuff.writeByte(0);
|
||||||
|
}
|
||||||
|
|
||||||
*dst = outbuff.data();
|
*dst = outbuff.data();
|
||||||
return (atUint32)outbuff.length();
|
return static_cast<atUint32>(outbuff.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
|
atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) {
|
||||||
if (*(atUint8*)(src) != 0x11)
|
if (*src != 0x11) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
atUint32 uncompressedLen = *(atUint32*)(src);
|
atUint32 uncompressedLen;
|
||||||
|
std::memcpy(&uncompressedLen, src, sizeof(uncompressedLen));
|
||||||
athena::utility::LittleUint32(uncompressedLen); // The compressed file has the filesize encoded in little endian
|
athena::utility::LittleUint32(uncompressedLen); // The compressed file has the filesize encoded in little endian
|
||||||
uncompressedLen = uncompressedLen >> 8; // First byte is the encode flag
|
uncompressedLen = uncompressedLen >> 8; // First byte is the encode flag
|
||||||
atUint32 currentOffset = 4;
|
atUint32 currentOffset = 4;
|
||||||
|
|
||||||
if (uncompressedLen ==
|
// If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes
|
||||||
0) // If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes
|
if (uncompressedLen == 0) {
|
||||||
{
|
atUint32 filesize;
|
||||||
atUint32 filesize = *(atUint32*)(src + 4);
|
std::memcpy(&filesize, src + 4, sizeof(filesize));
|
||||||
filesize = athena::utility::LittleUint32(filesize);
|
filesize = athena::utility::LittleUint32(filesize);
|
||||||
currentOffset += 4;
|
currentOffset += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
atUint8* uncompressedData = new atUint8[uncompressedLen];
|
auto uncompressedData = std::unique_ptr<atUint8[]>(new atUint8[uncompressedLen]);
|
||||||
atUint8* outputPtr = uncompressedData;
|
atUint8* outputPtr = uncompressedData.get();
|
||||||
atUint8* outputEndPtr = uncompressedData + uncompressedLen;
|
atUint8* outputEndPtr = uncompressedData.get() + uncompressedLen;
|
||||||
atUint8* inputPtr = (atUint8*)src + currentOffset;
|
const atUint8* inputPtr = src + currentOffset;
|
||||||
atUint8* inputEndPtr = (atUint8*)src + srcLength;
|
const atUint8* inputEndPtr = src + srcLength;
|
||||||
|
|
||||||
LZLengthOffset decoding;
|
LZLengthOffset decoding;
|
||||||
atUint8 maxTwoByteMatch = 0xF + 1;
|
const atUint8 maxTwoByteMatch = 0xF + 1;
|
||||||
atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes
|
const atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes
|
||||||
atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm;
|
const atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm;
|
||||||
atUint16 fourByteDenorm = maxThreeByteMatch + 1;
|
const atUint16 fourByteDenorm = maxThreeByteMatch + 1;
|
||||||
|
|
||||||
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
|
while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) {
|
||||||
|
const 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
|
// Checks to see if the next byte is compressed by looking
|
||||||
// at its binary representation - E.g 10010000
|
// at its binary representation - E.g 10010000
|
||||||
// This says that the first extracted byte and the four extracted byte is compressed
|
// This says that the first extracted byte and the four extracted byte is compressed
|
||||||
if ((isCompressed >> (7 - i)) & 0x1) {
|
if ((isCompressed >> (7 - i)) & 0x1) {
|
||||||
atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits
|
const atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits
|
||||||
|
|
||||||
if (metaDataSize >= 2) // Two Bytes of Length/Offset MetaData
|
if (metaDataSize >= 2) { // Two Bytes of Length/Offset MetaData
|
||||||
{
|
|
||||||
atUint16 lenOff = 0;
|
atUint16 lenOff = 0;
|
||||||
memcpy(&lenOff, inputPtr, 2);
|
memcpy(&lenOff, inputPtr, 2);
|
||||||
inputPtr += 2;
|
inputPtr += 2;
|
||||||
athena::utility::BigUint16(lenOff);
|
athena::utility::BigUint16(lenOff);
|
||||||
decoding.length = (lenOff >> 12) + 1;
|
decoding.length = (lenOff >> 12) + 1;
|
||||||
decoding.offset = (lenOff & 0xFFF) + 1;
|
decoding.offset = (lenOff & 0xFFF) + 1;
|
||||||
} else if (metaDataSize == 0) // Three Bytes of Length/Offset MetaData
|
} else if (metaDataSize == 0) { // Three Bytes of Length/Offset MetaData
|
||||||
{
|
|
||||||
atUint32 lenOff = 0;
|
atUint32 lenOff = 0;
|
||||||
memcpy((atUint8*)&lenOff + 1, inputPtr, 3);
|
memcpy(reinterpret_cast<atUint8*>(&lenOff) + 1, inputPtr, 3);
|
||||||
inputPtr += 3;
|
inputPtr += 3;
|
||||||
athena::utility::BigUint32(lenOff);
|
athena::utility::BigUint32(lenOff);
|
||||||
decoding.length = (lenOff >> 12) + threeByteDenorm;
|
decoding.length = (lenOff >> 12) + threeByteDenorm;
|
||||||
decoding.offset = (lenOff & 0xFFF) + 1;
|
decoding.offset = (lenOff & 0xFFF) + 1;
|
||||||
} else if (metaDataSize == 1) // Four Bytes of Length/Offset MetaData
|
} else if (metaDataSize == 1) { // Four Bytes of Length/Offset MetaData
|
||||||
{
|
|
||||||
atUint32 lenOff = 0;
|
atUint32 lenOff = 0;
|
||||||
memcpy(&lenOff, inputPtr, 4);
|
memcpy(&lenOff, inputPtr, 4);
|
||||||
inputPtr += 4;
|
inputPtr += 4;
|
||||||
|
@ -182,30 +184,30 @@ atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLen
|
||||||
decoding.length = ((lenOff >> 12) & 0xFFFF) + fourByteDenorm; // Gets rid of the Four byte flag
|
decoding.length = ((lenOff >> 12) & 0xFFFF) + fourByteDenorm; // Gets rid of the Four byte flag
|
||||||
decoding.offset = (lenOff & 0xFFF) + 1;
|
decoding.offset = (lenOff & 0xFFF) + 1;
|
||||||
} else {
|
} else {
|
||||||
delete[] uncompressedData;
|
|
||||||
uncompressedData = nullptr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((outputPtr - decoding.offset) < uncompressedData) // If the offset to look for uncompressed is passed the
|
// If the offset to look for uncompressed is passed the
|
||||||
// current uncompresed data then the data is not compressed
|
// current uncompresed data then the data is not compressed
|
||||||
{
|
if ((outputPtr - decoding.offset) < uncompressedData.get()) {
|
||||||
delete[] uncompressedData;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (atUint32 j = 0; j < decoding.length; ++j)
|
for (size_t j = 0; j < decoding.length; ++j) {
|
||||||
outputPtr[j] = (outputPtr - decoding.offset)[j];
|
outputPtr[j] = (outputPtr - decoding.offset)[j];
|
||||||
|
}
|
||||||
|
|
||||||
outputPtr += decoding.length;
|
outputPtr += decoding.length;
|
||||||
} else
|
} else {
|
||||||
*outputPtr++ = *inputPtr++;
|
*outputPtr++ = *inputPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr))
|
if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*dst = uncompressedData;
|
*dst = uncompressedData.release();
|
||||||
return uncompressedLen;
|
return uncompressedLen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,9 @@ atUint16 crc16CCITT(const atUint8* data, atUint64 length, atUint16 seed, atUint1
|
||||||
}
|
}
|
||||||
|
|
||||||
atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) {
|
atUint16 crc16(const atUint8* data, atUint64 length, atUint16 seed, atUint64 final) {
|
||||||
if (data)
|
if (data == nullptr) {
|
||||||
return seed;
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
static const atUint16 crc16Table[256] = {
|
static const atUint16 crc16Table[256] = {
|
||||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
|
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
|
||||||
|
|
|
@ -303,8 +303,9 @@ atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMat
|
||||||
}
|
}
|
||||||
|
|
||||||
atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) {
|
atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) {
|
||||||
if (*(atUint8*)src == 0x11)
|
if (*src == 0x11) {
|
||||||
return LZType11().decompress(src, dst, srcLen);
|
return LZType11().decompress(src, dst, srcLen);
|
||||||
|
}
|
||||||
|
|
||||||
return LZType10(2).decompress(src, dst, srcLen);
|
return LZType10(2).decompress(src, dst, srcLen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "athena/FileWriter.hpp"
|
#include "athena/FileWriter.hpp"
|
||||||
#include "win32_largefilewrapper.h"
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace athena::io {
|
namespace athena::io {
|
||||||
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr)
|
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr)
|
||||||
|
@ -89,26 +91,36 @@ atUint64 FileWriter::position() const {
|
||||||
LARGE_INTEGER li = {};
|
LARGE_INTEGER li = {};
|
||||||
LARGE_INTEGER res;
|
LARGE_INTEGER res;
|
||||||
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
|
SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT);
|
||||||
return res.QuadPart;
|
return static_cast<atUint64>(res.QuadPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void FileWriter::writeUBytes(const atUint8* data, atUint64 len) {
|
||||||
if (!isOpen()) {
|
if (!isOpen()) {
|
||||||
if (m_globalErr)
|
if (m_globalErr) {
|
||||||
atError(fmt("File not open for writing"));
|
atError(fmt("File not open for writing"));
|
||||||
|
}
|
||||||
setError();
|
setError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD ret = 0;
|
atUint64 remaining = len;
|
||||||
WriteFile(m_fileHandle, data, len, &ret, nullptr);
|
do {
|
||||||
if (ret != len) {
|
const auto toWrite = static_cast<DWORD>(std::min(remaining, atUint64{std::numeric_limits<DWORD>::max()}));
|
||||||
if (m_globalErr)
|
DWORD written = 0;
|
||||||
atError(fmt("Unable to write to stream"));
|
|
||||||
setError();
|
if (WriteFile(m_fileHandle, data, toWrite, &written, nullptr) == FALSE) {
|
||||||
|
if (m_globalErr) {
|
||||||
|
atError(fmt("Unable to write to file"));
|
||||||
}
|
}
|
||||||
|
setError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining -= written;
|
||||||
|
data += written;
|
||||||
|
} while (remaining != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace athena::io
|
} // namespace athena::io
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif // HW_RVL
|
#endif // HW_RVL
|
||||||
|
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
|
|
||||||
namespace athena::io {
|
namespace athena::io {
|
||||||
MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr)
|
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) {
|
: m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
namespace athena::io {
|
namespace athena::io {
|
||||||
|
|
||||||
MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership)
|
MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership)
|
||||||
: m_data((atUint8*)data), m_length(length), m_position(0), m_bufferOwned(takeOwnership) {
|
: m_data(data), m_length(length), m_bufferOwned(takeOwnership) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
atError(fmt("data cannot be NULL"));
|
atError(fmt("data cannot be NULL"));
|
||||||
setError();
|
setError();
|
||||||
|
@ -156,7 +156,7 @@ void MemoryWriter::setData(atUint8* data, atUint64 length, bool takeOwnership) {
|
||||||
if (m_bufferOwned)
|
if (m_bufferOwned)
|
||||||
delete m_data;
|
delete m_data;
|
||||||
|
|
||||||
m_data = (atUint8*)data;
|
m_data = data;
|
||||||
m_length = length;
|
m_length = length;
|
||||||
m_position = 0;
|
m_position = 0;
|
||||||
m_bufferOwned = takeOwnership;
|
m_bufferOwned = takeOwnership;
|
||||||
|
@ -185,11 +185,11 @@ void MemoryWriter::save(std::string_view filename) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filename.empty())
|
if (!filename.empty()) {
|
||||||
m_filepath = filename;
|
m_filepath = filename;
|
||||||
|
}
|
||||||
|
|
||||||
FILE* out = fopen(m_filepath.c_str(), "wb");
|
std::unique_ptr<FILE, decltype(&std::fclose)> out{std::fopen(m_filepath.c_str(), "wb"), std::fclose};
|
||||||
|
|
||||||
if (!out) {
|
if (!out) {
|
||||||
atError(fmt("Unable to open file '{}'"), m_filepath);
|
atError(fmt("Unable to open file '{}'"), m_filepath);
|
||||||
setError();
|
setError();
|
||||||
|
@ -200,22 +200,24 @@ void MemoryWriter::save(std::string_view filename) {
|
||||||
atUint64 blocksize = BLOCKSZ;
|
atUint64 blocksize = BLOCKSZ;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (blocksize > m_length - done)
|
if (blocksize > m_length - done) {
|
||||||
blocksize = m_length - done;
|
blocksize = m_length - done;
|
||||||
|
}
|
||||||
|
|
||||||
atInt64 ret = fwrite(m_data + done, 1, blocksize, out);
|
const atInt64 ret = std::fwrite(m_data + done, 1, blocksize, out.get());
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
atError(fmt("Error writing data to disk"));
|
atError(fmt("Error writing data to disk"));
|
||||||
setError();
|
setError();
|
||||||
return;
|
return;
|
||||||
} else if (ret == 0)
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
done += blocksize;
|
done += blocksize;
|
||||||
} while (done < m_length);
|
} while (done < m_length);
|
||||||
|
|
||||||
fclose(out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) {
|
void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) {
|
||||||
|
@ -258,15 +260,14 @@ void MemoryCopyWriter::resize(atUint64 newSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and copy new buffer
|
// Allocate and copy new buffer
|
||||||
atUint8* newArray = new atUint8[newSize];
|
auto newArray = std::make_unique<atUint8[]>(newSize);
|
||||||
memset(newArray, 0, newSize);
|
if (m_dataCopy) {
|
||||||
|
std::memmove(newArray.get(), m_dataCopy.get(), m_length);
|
||||||
if (m_dataCopy)
|
}
|
||||||
memmove(newArray, m_dataCopy.get(), m_length);
|
m_dataCopy = std::move(newArray);
|
||||||
m_dataCopy.reset(newArray);
|
|
||||||
|
|
||||||
// Swap the pointer and size out for the new ones.
|
// Swap the pointer and size out for the new ones.
|
||||||
m_data = newArray;
|
m_data = m_dataCopy.get();
|
||||||
m_length = newSize;
|
m_length = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue