diff --git a/.gitmodules b/.gitmodules index fd10e33..ba67437 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,7 +2,3 @@ path = extern/lzokay url = https://github.com/AxioDL/lzokay.git branch = master -[submodule "extern/fmt"] - path = extern/fmt - url = https://github.com/fmtlib/fmt - branch = master diff --git a/CMakeLists.txt b/CMakeLists.txt index 70eed37..4a5b259 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,6 @@ add_library(athena-core src/LZ77/LZBase.cpp src/athena/FileInfo.cpp src/athena/Dir.cpp - src/athena/DNAYaml.cpp include/athena/IStream.hpp include/athena/IStreamReader.hpp @@ -179,9 +178,6 @@ add_library(athena-core include/LZ77/LZType11.hpp include/athena/FileInfo.hpp include/athena/Dir.hpp - include/athena/DNA.hpp - include/athena/DNAYaml.hpp - include/athena/DNAOp.hpp include/athena/YAMLCommon.hpp include/athena/YAMLDocReader.hpp include/athena/YAMLDocWriter.hpp @@ -225,7 +221,6 @@ target_include_directories(athena-core PUBLIC ) target_link_libraries(athena-core PUBLIC athena-libyaml - fmt $ ) @@ -245,6 +240,9 @@ add_library(athena-sakura EXCLUDE_FROM_ALL include/athena/SpriteFrame.hpp include/athena/SpritePart.hpp ) +target_include_directories(athena-sakura PUBLIC + include +) add_library(athena-wiisave EXCLUDE_FROM_ALL src/athena/WiiBanner.cpp @@ -271,6 +269,9 @@ add_library(athena-wiisave EXCLUDE_FROM_ALL include/md5.h include/sha1.h ) +target_include_directories(athena-wiisave PUBLIC + include +) if(NOT MSVC AND ${CMAKE_SYSTEM_PROCESSOR} STREQUAL x86_64) set_source_files_properties(src/aes.cpp PROPERTIES COMPILE_FLAGS -maes) endif() @@ -310,7 +311,9 @@ add_library(athena-zelda EXCLUDE_FROM_ALL include/athena/ZQuestFileReader.hpp include/athena/ZQuestFileWriter.hpp ) - +target_include_directories(athena-zelda PUBLIC + include +) # Icon set(ATHENA_ICO ${CMAKE_CURRENT_SOURCE_DIR}/Athena.ico) @@ -331,12 +334,9 @@ endforeach() # Define installs install(DIRECTORY include/athena DESTINATION ${INSTALL_INCLUDE_DIR} COMPONENT athena) -install(DIRECTORY extern/fmt/include/fmt DESTINATION ${INSTALL_INCLUDE_DIR} COMPONENT athena) if (ATHENA_ZLIB) set(ZLIB_INSTALL ${ZLIB_LIBRARIES}) endif () -install(TARGETS athena-core fmt ${ZLIB_INSTALL} - DESTINATION ${INSTALL_LIB_DIR} EXPORT AthenaTargets COMPONENT athena) if(WIN32 AND NOT CYGWIN) install(FILES Athena.ico DESTINATION ${INSTALL_LIB_DIR} COMPONENT athena) elseif(UNIX) @@ -350,9 +350,6 @@ endif() # Package Export # ################## -# Add all targets to the build-tree export set -export(TARGETS athena-core athena-libyaml fmt ${ZLIB_LIBRARIES} FILE "${CMAKE_CURRENT_BINARY_DIR}/AthenaTargets.cmake") - # Export the package for use from the build-tree # (this registers the build-tree with a global CMake-registry) export(PACKAGE athena) @@ -380,23 +377,6 @@ install(FILES # Install the export set for use with the install-tree install(EXPORT AthenaTargets DESTINATION ${INSTALL_CMAKE_DIR} COMPONENT athena) -################ -# atdna import # -################ - -add_subdirectory(atdna) -if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) -# Test target -add_executable(atdna-test atdna/test.cpp atdna/test.hpp) -if (CMAKE_SYSTEM_NAME STREQUAL "Switch") - set_target_properties(atdna-test PROPERTIES SUFFIX ".elf") - target_link_libraries(atdna-test athena-core nx) -else() - target_link_libraries(atdna-test athena-core) -endif() -target_atdna(atdna-test atdna_test.cpp atdna/test.hpp) -endif() - ######### # CPack # ######### diff --git a/atdna/CMakeLists.txt b/atdna/CMakeLists.txt deleted file mode 100644 index 1b25983..0000000 --- a/atdna/CMakeLists.txt +++ /dev/null @@ -1,171 +0,0 @@ -############### -# ATDNA Build # -############### - -if(NOT TARGET atdna AND NOT CMAKE_CROSSCOMPILING) - -get_directory_property(ATDNA_DEFINES COMPILE_DEFINITIONS) -list(REMOVE_ITEM ATDNA_DEFINES _GLIBCXX_DEBUG=1) -set_directory_properties(PROPERTIES COMPILE_DEFINITIONS "${ATDNA_DEFINES}") - -# Find dependencies -if (NOT "${LLVM_ROOT_DIR}" STREQUAL "") - # use existing LLVM_ROOT_DIR -elseif (APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - set(LLVM_ROOT_DIR /usr/local/opt/llvm) -elseif (APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) - set(LLVM_ROOT_DIR /opt/homebrew/opt/llvm) -elseif (WIN32) - get_filename_component(LLVM_ROOT_DIR [HKEY_LOCAL_MACHINE\\Software\\LLVM\\LLVM] ABSOLUTE) -else () - set(LLVM_ROOT_DIR "") -endif () -find_package(Clang REQUIRED PATHS ${LLVM_ROOT_DIR}) -find_package(LLVM REQUIRED PATHS ${CLANG_INSTALL_PREFIX}) - -if(LLVM_FOUND) - -if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - option(ATDNA_DYNAMIC_LLVM "Use dynamic library targets when linking LLVM" ON) -else() - option(ATDNA_DYNAMIC_LLVM "Use dynamic library targets when linking LLVM" OFF) -endif() - -set(CLANG_LIBS "") -set(LLVM_LIBS "") - -if (ATDNA_DYNAMIC_LLVM) - list(APPEND CLANG_LIBS clang-cpp) - list(APPEND LLVM_LIBS LLVM) -else() - function(recursive_remove_library target library) - get_target_property(target_dependencies ${target} INTERFACE_LINK_LIBRARIES) - foreach(dep ${target_dependencies}) - if (NOT "${dep}" STREQUAL "${library}" AND TARGET "${dep}") - recursive_remove_library(${dep} ${library}) - endif() - endforeach() - list(FIND target_dependencies "${library}" list_index) - if (${list_index} GREATER -1) - list(REMOVE_AT target_dependencies ${list_index}) - set_property(TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES "${target_dependencies}") - endif() - endfunction() - - # Add LLVM static libs - list(APPEND CLANG_LIBS clangTooling) - list(APPEND LLVM_LIBS LLVMFrontendOpenMP LLVMOption) - # Remove LLVM dynamic library from Clang dependencies - foreach (lib ${CLANG_LIBS}) - recursive_remove_library(${lib} LLVM) - endforeach () - # Hack around link order issues - target_link_libraries(clangAST INTERFACE LLVMFrontendOpenMP) -endif() - -# Offer the user the choice of overriding the installation directories -set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") -set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") -set(INSTALL_CMAKE_DIR lib/cmake/atdna) - -# Make relative paths absolute (needed later on) -foreach(p BIN INCLUDE CMAKE) - set(var INSTALL_${p}_DIR) - if(NOT IS_ABSOLUTE "${${var}}") - set(ABS_${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") - else() - set(ABS_${var} "${${var}}") - endif() -endforeach() - -# Windows resource -if(WIN32) - configure_file(main.rc.in main.rc @ONLY) - set(PLAT_SRCS ${CMAKE_CURRENT_BINARY_DIR}/main.rc) -endif() - -# ATDNA target -add_executable(atdna main.cpp test.hpp ${PLAT_SRCS}) -target_link_libraries(atdna ${CLANG_LIBS} ${LLVM_LIBS}) -if (APPLE) - set(ATDNA_ARGV0 clang-tool) -else () - set(ATDNA_ARGV0 "${LLVM_TOOLS_BINARY_DIR}/clang-tool") -endif () -target_compile_definitions(atdna PRIVATE - INSTALL_PREFIX=${ABS_INSTALL_BIN_DIR} - __STDC_LIMIT_MACROS=1 - __STDC_CONSTANT_MACROS=1 - ATDNA_ARGV0=${ATDNA_ARGV0}) -target_include_directories(atdna PRIVATE ${CLANG_INCLUDE_DIRS}) -# Clang 10.0.x headers currently broken with C++20 -set_property(TARGET atdna PROPERTY CXX_STANDARD 17) -if(MSVC) - if (VCPKG_TOOLCHAIN) - # Assumes static build of LLVM - if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set_property(TARGET atdna PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDebug") - else () - set_property(TARGET atdna PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") - endif () - else () - # Allow linking against release-built LLVM libraries - target_compile_options(atdna PRIVATE /GR- /D_ITERATOR_DEBUG_LEVEL=0) - set_property(TARGET atdna PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") - endif () -else () - target_compile_options(atdna PRIVATE -fno-rtti -fvisibility=hidden -Wno-error) - if (METAFORCE_ASAN AND CMAKE_SYSTEM_NAME STREQUAL "Linux") - # On Linux, we need to compile without ASAN; explicitly disable it here - target_compile_options(atdna PRIVATE -stdlib=libstdc++ -fno-sanitize=address) - target_link_options(atdna PRIVATE -stdlib=libstdc++ -fno-sanitize=address) - endif () -endif() - -# Define installs -install(TARGETS atdna DESTINATION ${INSTALL_BIN_DIR} EXPORT atdnaTargets COMPONENT atdna) -install(DIRECTORY ${LLVM_INCLUDE_DIR}/clang DESTINATION ${INSTALL_INCLUDE_DIR}/athena COMPONENT atdna) - -################## -# Package Export # -################## - -# Add all targets to the build-tree export set -export(TARGETS atdna FILE "${CMAKE_CURRENT_BINARY_DIR}/atdnaTargets.cmake") - -# Export the package for use from the build-tree -# (this registers the build-tree with a global CMake-registry) -export(PACKAGE atdna) - -# Create the atdnaConfig.cmake -# ... for the build tree -configure_file(atdnaConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/atdnaConfig.cmake" @ONLY) -# ... for the install tree -configure_file(atdnaConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/atdnaConfig.cmake" @ONLY) -# ... for both -configure_file(atdnaConfigVersion.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/atdnaConfigVersion.cmake" @ONLY) - -# Install atdnaConfig.cmake -install(FILES - "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/atdnaConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/atdnaConfigVersion.cmake" - DESTINATION ${INSTALL_CMAKE_DIR} COMPONENT atdna) - -# Install the export set for use with the install-tree -install(EXPORT atdnaTargets DESTINATION ${INSTALL_CMAKE_DIR} COMPONENT atdna) - -######### -# CTest # -######### - -if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) -enable_testing() -add_test(NAME test-dna COMMAND $ -o test.cpp - "-I${ATHENA_INCLUDE_DIR}" ${CMAKE_SOURCE_DIR}/test.hpp) -endif() - -endif() - -endif() - -include(atdnaHelpers.cmake) diff --git a/atdna/README.md b/atdna/README.md deleted file mode 100644 index 7e08d40..0000000 --- a/atdna/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# atdna -[User Overview](http://libAthena.github.io/doc/atdna.html) -[DNA Record Reference](http://libAthena.github.io/doc/atdna-ref.html) diff --git a/atdna/atdnaConfig.cmake.in b/atdna/atdnaConfig.cmake.in deleted file mode 100644 index e045ec4..0000000 --- a/atdna/atdnaConfig.cmake.in +++ /dev/null @@ -1,88 +0,0 @@ -# - Config file for the atdna package - -# Compute paths -get_filename_component(ATDNA_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) - -# Our library dependencies (contains definitions for IMPORTED targets) -if(NOT TARGET atdna AND NOT atdna_BINARY_DIR) - include("${ATDNA_CMAKE_DIR}/atdnaTargets.cmake") -endif() - -# Super handy macro for adding atdna target -function(atdna out) - # Ninja wants invocations in root binary dir for DEPFILE application - file(RELATIVE_PATH out_rel ${CMAKE_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/${out}") - - # Make input files source-relative - set(ins "") - set(ins_impdeps "") - foreach(arg ${ARGN}) - list(APPEND ins ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) - list(APPEND ins_impdeps CXX) - list(APPEND ins_impdeps ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) - endforeach() - - # Get local include directories for atdna - get_property(incdirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) - set(inccli "") - foreach(dir ${incdirs}) - if (NOT dir MATCHES ".*emscripten.*") - list(APPEND inccli "-I${dir}") - endif() - endforeach() - - # Get local defines for atdna - get_property(cdefs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS) - set(cdefcli "") - foreach(def ${cdefs}) - list(APPEND cdefcli "-D${def}") - endforeach() - - # MS extra - unset(extraargs) - if(MSVC) - list(APPEND extraargs -fms-compatibility -fexceptions) - if(MSVC_VERSION EQUAL 1800) - list(APPEND extraargs -fms-compatibility-version=18.00) - elseif(MSVC_VERSION EQUAL 1900) - list(APPEND extraargs -fms-compatibility-version=19.00) - elseif(MSVC_VERSION EQUAL 1910) - list(APPEND extraargs -fms-compatibility-version=19.10) - elseif(MSVC_VERSION EQUAL 1911) - list(APPEND extraargs -fms-compatibility-version=19.11) - endif() - - # OSX Extra - elseif(APPLE) - get_filename_component(COMPILER_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY) - if (NOT EXISTS "${CMAKE_OSX_SYSROOT}") - message(FATAL_ERROR "CMAKE_OSX_SYSROOT not set") - endif() - file(GLOB SYSTEM_INCLUDE_DIR "${COMPILER_DIR}/../lib/clang/*/include") - list(APPEND extraargs - -isysroot ${CMAKE_OSX_SYSROOT} - -stdlib++-isystem "${COMPILER_DIR}/../include/c++/v1" - -isystem "${SYSTEM_INCLUDE_DIR}") - endif() - - # Make target - if(${CMAKE_GENERATOR} STREQUAL "Ninja") - # Use Ninja's DEPFILE parser in cooperation with atdna - add_custom_command(OUTPUT ${out} COMMAND $ - ARGS ${extraargs} -o ${out_rel} -MD -MT ${out_rel} -MF ${out_rel}.d ${cdefcli} ${inccli} - "-I${ATHENA_INCLUDE_DIR}" ${ins} - DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} - DEPFILE "${CMAKE_CURRENT_BINARY_DIR}/${out}.d" - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating DNA ${out_rel}") - else() - # Use CMake's built-in dependency scanner for makefile targets - add_custom_command(OUTPUT ${out} COMMAND $ - ARGS ${extraargs} -o ${out_rel} ${cdefcli} ${inccli} - "-I${ATHENA_INCLUDE_DIR}" ${ins} - DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating DNA ${out_rel}") - endif() -endfunction() - diff --git a/atdna/atdnaConfigVersion.cmake.in b/atdna/atdnaConfigVersion.cmake.in deleted file mode 100644 index 92aaced..0000000 --- a/atdna/atdnaConfigVersion.cmake.in +++ /dev/null @@ -1,12 +0,0 @@ -set(PACKAGE_VERSION "@ATHENA_VERSION_STRING@") - -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() - diff --git a/atdna/atdnaHelpers.cmake b/atdna/atdnaHelpers.cmake deleted file mode 100644 index a3e7016..0000000 --- a/atdna/atdnaHelpers.cmake +++ /dev/null @@ -1,164 +0,0 @@ -# -# gather_include_directories recursively builds a list of include directories -# across all dependencies. -# - -if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") - # Don't transform add_custom_command DEPFILE for Ninja - cmake_policy(SET CMP0116 OLD) -endif () - -function(_atdna_gather_include_directories_impl target_name) - get_target_property(target_dependencies ${target_name} INTERFACE_LINK_LIBRARIES) - foreach(dep ${target_dependencies}) - if(TARGET ${dep}) - get_target_property(dep_includes ${dep} INTERFACE_INCLUDE_DIRECTORIES) - if(dep_includes) - list(APPEND target_includes ${dep_includes}) - endif() - _atdna_gather_include_directories_impl(${dep}) - endif() - endforeach() - set(target_includes ${target_includes} PARENT_SCOPE) -endfunction() - -function(atdna_gather_include_directories var target_name) - unset(target_includes) - get_directory_property(dir_includes INCLUDE_DIRECTORIES) - if(dir_includes) - list(APPEND target_includes ${dir_includes}) - endif() - get_target_property(target_includes1 ${target_name} INCLUDE_DIRECTORIES) - if(target_includes1) - list(APPEND target_includes ${target_includes1}) - endif() - get_target_property(target_includes2 ${target_name} INTERFACE_INCLUDE_DIRECTORIES) - if(target_includes2) - list(APPEND target_includes ${target_includes2}) - endif() - _atdna_gather_include_directories_impl(${target_name}) - list(REMOVE_DUPLICATES target_includes) - set(${var} ${target_includes} PARENT_SCOPE) -endfunction() - -function(_atdna_gather_compile_definitions_impl target_name) - get_target_property(target_dependencies ${target_name} INTERFACE_LINK_LIBRARIES) - foreach(dep ${target_dependencies}) - if(TARGET ${dep}) - get_target_property(dep_defines ${dep} INTERFACE_COMPILE_DEFINITIONS) - if(dep_defines) - list(APPEND target_defines ${dep_defines}) - endif() - _atdna_gather_compile_definitions_impl(${dep}) - endif() - endforeach() - set(target_defines ${target_defines} PARENT_SCOPE) -endfunction() - -function(atdna_gather_compile_definitions var target_name) - unset(target_defines) - get_directory_property(dir_defines COMPILE_DEFINITIONS) - if(dir_defines) - list(APPEND target_defines ${dir_defines}) - endif() - get_target_property(target_defines1 ${target_name} COMPILE_DEFINITIONS) - if(target_defines1) - list(APPEND target_defines ${target_defines1}) - endif() - get_target_property(target_defines2 ${target_name} INTERFACE_COMPILE_DEFINITIONS) - if(target_defines2) - list(APPEND target_defines ${target_defines2}) - endif() - _atdna_gather_compile_definitions_impl(${target_name}) - list(REMOVE_DUPLICATES target_defines) - set(${var} ${target_defines} PARENT_SCOPE) -endfunction() - -####################### -# In-tree atdna macro # -####################### - -# Super handy macro for adding atdna target -function(atdna out incdirs cdefs) - # Ninja wants invocations in root binary dir for DEPFILE application - file(RELATIVE_PATH out_rel ${CMAKE_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/${out}") - - # Make input files source-relative - unset(ins) - unset(ins_impdeps) - foreach(arg ${ARGN}) - list(APPEND ins ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) - list(APPEND ins_impdeps CXX) - list(APPEND ins_impdeps ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) - endforeach() - - set(inccli "") - foreach(dir ${incdirs}) - if (NOT dir MATCHES ".*emscripten.*") - list(APPEND inccli "-I${dir}") - endif() - endforeach() - - set(cdefcli "") - foreach(def ${cdefs}) - list(APPEND cdefcli "-D${def}") - endforeach() - - # MS extra - unset(extraargs) - if(MSVC) - list(APPEND extraargs -fms-compatibility -fexceptions) - if(MSVC_VERSION EQUAL 1800) - list(APPEND extraargs -fms-compatibility-version=18.00) - elseif(MSVC_VERSION EQUAL 1900) - list(APPEND extraargs -fms-compatibility-version=19.00) - elseif(MSVC_VERSION EQUAL 1910) - list(APPEND extraargs -fms-compatibility-version=19.10) - elseif(MSVC_VERSION EQUAL 1911) - list(APPEND extraargs -fms-compatibility-version=19.11) - endif() - - # OSX Extra - elseif(APPLE) - get_filename_component(COMPILER_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY) - if (NOT EXISTS "${CMAKE_OSX_SYSROOT}") - message(FATAL_ERROR "CMAKE_OSX_SYSROOT not set") - endif() - file(GLOB SYSTEM_INCLUDE_DIR "${COMPILER_DIR}/../lib/clang/*/include") - list(APPEND extraargs - -isysroot ${CMAKE_OSX_SYSROOT} - -stdlib++-isystem "${COMPILER_DIR}/../include/c++/v1" - -isystem "${SYSTEM_INCLUDE_DIR}") - endif() - - # Make target - if(${CMAKE_GENERATOR} STREQUAL "Ninja") - # Use Ninja's DEPFILE parser in cooperation with atdna - add_custom_command(OUTPUT ${out} COMMAND $ - ARGS ${extraargs} -o ${out_rel} -MD -MT ${out_rel} -MF ${out_rel}.d - ${inccli} ${cdefcli} - "-I${athena_SOURCE_DIR}/include" ${ins} - DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} - DEPFILE "${CMAKE_CURRENT_BINARY_DIR}/${out}.d" - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating DNA ${out_rel}" - COMMAND_EXPAND_LISTS) - else() - # Use CMake's built-in dependency scanner for makefile targets - add_custom_command(OUTPUT ${out} COMMAND $ - ARGS ${extraargs} -o ${out_rel} - ${inccli} ${cdefcli} - "-I${athena_SOURCE_DIR}/include" ${ins} - DEPENDS atdna ${ins} IMPLICIT_DEPENDS ${ins_impdeps} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating DNA ${out_rel}" - COMMAND_EXPAND_LISTS) - endif() -endfunction() - -function(target_atdna target out) - atdna_gather_include_directories(include_list ${target}) - atdna_gather_compile_definitions(define_list ${target}) - atdna(${out} "${include_list}" "${define_list}" ${ARGN}) - target_sources(${target} PRIVATE ${out} ${ARGN}) -endfunction() diff --git a/atdna/main.cpp b/atdna/main.cpp deleted file mode 100644 index d9e6e65..0000000 --- a/atdna/main.cpp +++ /dev/null @@ -1,1354 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace std::literals; - -static unsigned AthenaError = 0; -#define ATHENA_DNA_BASETYPE "struct athena::io::DNA" - -#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::opt Verbose("v", llvm::cl::desc("verbose mode")); - -static llvm::cl::OptionCategory ATDNAFormatCategory("atdna options"); - -static llvm::cl::opt OutputFilename("o", llvm::cl::desc("Specify output filename"), - llvm::cl::value_desc("filename"), llvm::cl::Prefix); - -static llvm::cl::opt FExceptions("fexceptions", llvm::cl::desc("Enable C++ Exceptions")); -static llvm::cl::opt FMSCompat("fms-compatibility", llvm::cl::desc("Enable MS header compatibility")); -static llvm::cl::opt - FMSCompatVersion("fms-compatibility-version", - llvm::cl::desc("Specify MS compatibility version (18.00 for VS2013, 19.00 for VS2015)")); - -static llvm::cl::list InputFilenames(llvm::cl::Positional, llvm::cl::desc(""), - llvm::cl::ZeroOrMore); - -static llvm::cl::list IncludeSearchPaths("I", llvm::cl::desc("Header search path"), llvm::cl::Prefix); - -static llvm::cl::list SystemIncludeSearchPaths("isystem", llvm::cl::desc("System Header search path")); - -static llvm::cl::list StandardCXXLibISystem("stdlib++-isystem", - llvm::cl::desc("Standard C++ library search path")); - -static llvm::cl::opt StandardCXXLib("stdlib", llvm::cl::desc("Standard C++ library")); - -static llvm::cl::opt DepFile("MD", llvm::cl::desc("Make Dependency file")); - -static llvm::cl::opt DepFileOut("MF", llvm::cl::desc("Dependency file out path")); - -static llvm::cl::list DepFileTargets("MT", llvm::cl::desc("Dependency file targets")); - -static llvm::cl::list SystemIncRoot("isysroot", llvm::cl::desc("System include root")); - -static llvm::cl::list PreprocessorDefines("D", llvm::cl::desc("Preprocessor define"), llvm::cl::Prefix); - -static llvm::cl::opt EmitIncludes("emit-includes", - llvm::cl::desc("Emit DNA for included files (not just main file)")); - -/* LLVM 3.7 changed the stream type */ -#if LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) -using StreamOut = llvm::raw_pwrite_stream; -#else -using StreamOut = llvm::raw_fd_ostream; -#endif - -#if LLVM_VERSION_MAJOR >= 12 -static inline bool GetIntegerConstantExpr(const clang::Expr* expr, llvm::APSInt& out, const clang::ASTContext& ctx) { - const auto optional = expr->getIntegerConstantExpr(ctx); - if (optional) { - out = optional.getValue(); - return true; - } - return false; -} -#else -static inline bool GetIntegerConstantExpr(const clang::Expr* expr, llvm::APSInt& out, const clang::ASTContext& ctx) { - return expr->isIntegerConstantExpr(out, ctx); -} -#endif - -class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { - clang::ASTContext& context; - StreamOut& fileOut; - - bool isDNARecord(const clang::CXXRecordDecl* record, std::string& baseDNA) { - for (const clang::CXXBaseSpecifier& base : record->bases()) { - const clang::QualType qtp = base.getType().getCanonicalType(); - if (!qtp.getAsString().compare(0, sizeof(ATHENA_DNA_BASETYPE) - 1, ATHENA_DNA_BASETYPE)) - return true; - } - for (const clang::CXXBaseSpecifier& base : record->bases()) { - clang::QualType qtp = base.getType().getCanonicalType(); - const clang::Type* tp = qtp.getTypePtrOrNull(); - if (tp) { - const clang::CXXRecordDecl* rDecl = tp->getAsCXXRecordDecl(); - if (rDecl) { - if (isDNARecord(rDecl, baseDNA)) { - bool hasRead = false; - bool hasWrite = false; - for (const clang::CXXMethodDecl* method : rDecl->methods()) { - std::string compName = method->getDeclName().getAsString(); - if (compName == "read") - hasRead = true; - else if (compName == "write") - hasWrite = true; - } - if (hasRead && hasWrite) { - std::string templateStmt; - GetNestedTypeName(rDecl, templateStmt, baseDNA); - } - return true; - } - } - } - } - return false; - } - - int64_t GetSizeValue(const clang::Type* theType, unsigned width) { - if (theType->isEnumeralType()) { - const auto* eType = static_cast(theType); - clang::EnumDecl* eDecl = eType->getDecl(); - theType = eDecl->getIntegerType().getCanonicalType().getTypePtr(); - - const auto* bType = static_cast(theType); - if (bType->isBooleanType()) { - return 1; - } else if (bType->isUnsignedInteger() || bType->isSignedInteger()) { - return width / 8; - } - } else if (theType->isBuiltinType()) { - const auto* bType = static_cast(theType); - if (bType->isBooleanType()) { - return 1; - } else if (bType->isUnsignedInteger() || bType->isSignedInteger() || bType->isFloatingPoint()) { - return width / 8; - } - } else if (theType->isRecordType()) { - const clang::CXXRecordDecl* rDecl = theType->getAsCXXRecordDecl(); - for (const clang::FieldDecl* field : rDecl->fields()) { - if (field->getName() == "clangVec") { - const auto* vType = static_cast(field->getType().getTypePtr()); - if (vType->isVectorType()) { - const auto* eType = static_cast(vType->getElementType().getTypePtr()); - const uint64_t typeWidth = context.getTypeInfo(eType).Width; - if (!eType->isBuiltinType() || !eType->isFloatingPoint() || (typeWidth != 32 && typeWidth != 64)) - continue; - if (vType->getNumElements() == 2) { - return typeWidth / 8 * 2; - } else if (vType->getNumElements() == 3) { - return typeWidth / 8 * 3; - } else if (vType->getNumElements() == 4) { - return typeWidth / 8 * 4; - } - } - } - } - } - return 0; - } - - static std::string GetFieldString(const std::string& fieldName) { -#if 0 - size_t underscorePos = fieldName.find('_'); - std::string idString = fieldName; - if (underscorePos != std::string::npos && underscorePos != fieldName.size() - 1) - idString.assign(fieldName.begin() + underscorePos + 1, fieldName.end()); - return idString; -#endif - return fieldName; - } - - static std::string GetPropIdExpr(const clang::FieldDecl* field, const std::string& fieldName) { - std::string fieldStr = GetFieldString(fieldName); - std::string propIdExpr = "\""s.append(fieldStr).append("\"sv"); - for (clang::Attr* attr : field->attrs()) { - if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) { - llvm::StringRef textRef = annot->getAnnotation(); -#if LLVM_VERSION_MAJOR >= 13 - if (textRef.startswith_insensitive("rcrc32=")) -#else - if (textRef.startswith_lower("rcrc32=")) -#endif - { - unsigned long num = strtoul(textRef.data() + 7, nullptr, 16); - std::string tmpS; - llvm::raw_string_ostream s(tmpS); - s << llvm::format("\"%s\"sv, 0x%08X", fieldStr.c_str(), num); - propIdExpr = s.str(); - break; - } - } - } - return propIdExpr; - } - - static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr, - const std::string& endianExpr) { - - return "(athena::io::PropId(") - .append(propIdExpr) - .append("), ") - .append(fieldName) - .append(", s)"); - } - - static std::string GetOpString(const std::string& fieldName, const std::string& propIdExpr) { - - return "(athena::io::PropId("s.append(propIdExpr).append("), ").append(fieldName).append(", s)"); - } - - static std::string GetVectorOpString(const std::string& fieldName, const std::string& propIdExpr, - const std::string& sizeExpr, const std::string& endianExpr) { - return "(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, - const std::string& sizeExpr) { - return "(athena::io::PropId("s.append(propIdExpr) - .append("), ") - .append(fieldName) - .append(", ") - .append(sizeExpr) - .append(", s)"); - } - - void RecurseNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) { - if (!decl) - return; - RecurseNestedTypeName(decl->getParent(), templateStmt, qualType); - if (const clang::CXXRecordDecl* rec = clang::dyn_cast_or_null(decl)) { - if (!qualType.empty()) - qualType += "::"; - qualType += rec->getName(); - const clang::ClassTemplateSpecializationDecl* cts = - clang::dyn_cast_or_null(rec); - if (cts && cts->isExplicitSpecialization()) { - qualType += '<'; - bool needsComma = false; - for (auto& arg : cts->getTemplateArgs().asArray()) { - if (needsComma) - qualType += ", "; - llvm::raw_string_ostream OS(qualType); -#if LLVM_VERSION_MAJOR >= 13 - arg.print(context.getPrintingPolicy(), OS, false); -#else - arg.print(context.getPrintingPolicy(), OS); -#endif - needsComma = true; - } - qualType += '>'; - } else if (const clang::ClassTemplateDecl* ct = rec->getDescribedClassTemplate()) { - templateStmt += "template <"; - qualType += '<'; - bool needsComma = false; - for (const clang::NamedDecl* parm : *ct->getTemplateParameters()) { - if (const clang::TemplateTypeParmDecl* tpParm = clang::dyn_cast_or_null(parm)) { - if (needsComma) { - templateStmt += ", "; - qualType += ", "; - } - templateStmt += "class "s.append(tpParm->getName().str()); - qualType += tpParm->getName(); - needsComma = true; - } else if (const clang::NonTypeTemplateParmDecl* nonTypeParm = - clang::dyn_cast_or_null(parm)) { - if (needsComma) { - templateStmt += ", "; - qualType += ", "; - } - templateStmt += nonTypeParm->getType() - .getAsString(context.getPrintingPolicy()) - .append(1, ' ') - .append(nonTypeParm->getName().str()); - qualType += nonTypeParm->getName(); - needsComma = true; - } - } - templateStmt += ">\n"; - qualType += '>'; - } - } else if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null(decl)) { - if (!qualType.empty()) - qualType += "::"; - qualType += namedDecl->getName(); - } - } - - void GetNestedTypeName(const clang::DeclContext* decl, std::string& templateStmt, std::string& qualType) { - templateStmt.clear(); - qualType.clear(); - RecurseNestedTypeName(decl, templateStmt, qualType); - } - - void RecurseNestedTypeSpecializations(const clang::DeclContext* decl, - std::vector>& specializations) { - if (!decl) { - specializations.emplace_back(); - return; - } - - std::vector> parentSpecializations; - RecurseNestedTypeSpecializations(decl->getParent(), parentSpecializations); - bool foundSpecializations = false; - if (const clang::CXXRecordDecl* rec = clang::dyn_cast_or_null(decl)) { - const clang::ClassTemplateSpecializationDecl* cts = - clang::dyn_cast_or_null(rec); - if (cts && cts->isExplicitSpecialization()) { - for (const auto& parent : parentSpecializations) { - if (parent.first.empty()) { - specializations.emplace_back(std::string(rec->getName().str()).append(1, '<'), 0); - } else { - auto specialization = std::string(parent.first).append("::").append(rec->getName().str()).append(1, '<'); - specializations.emplace_back(std::move(specialization), parent.second); - } - bool needsComma = false; - for (auto& arg : cts->getTemplateArgs().asArray()) { - if (needsComma) - specializations.back().first += ", "; - llvm::raw_string_ostream OS(specializations.back().first); -#if LLVM_VERSION_MAJOR >= 13 - arg.print(context.getPrintingPolicy(), OS, false); -#else - arg.print(context.getPrintingPolicy(), OS); -#endif - needsComma = true; - } - specializations.back().first += '>'; - } - foundSpecializations = true; - } else if (const clang::ClassTemplateDecl* ct = rec->getDescribedClassTemplate()) { - int numParms = 0; - for (const clang::NamedDecl* parm : *ct->getTemplateParameters()) - if (clang::dyn_cast_or_null(parm) || - clang::dyn_cast_or_null(parm)) - ++numParms; - - for (clang::Attr* attr : rec->attrs()) { - if (clang::AnnotateAttr* annot = clang::dyn_cast_or_null(attr)) { - llvm::StringRef textRef = annot->getAnnotation(); -#if LLVM_VERSION_MAJOR >= 13 - if (textRef.startswith_insensitive("specparms=")) -#else - if (textRef.startswith_lower("specparms=")) -#endif - { - llvm::SmallVector specParms; - textRef.substr(10).split(specParms, ','); - int numTuples = int(specParms.size()) / numParms; - for (const auto& parent : parentSpecializations) { - for (int i = 0; i < numTuples; ++i) { - if (parent.first.empty()) { - specializations.emplace_back(std::string(rec->getName().str()).append(1, '<'), 1); - } else { - 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; - for (auto it = specParms.begin() + i * numParms; - it != specParms.end() && it != specParms.begin() + (i + 1) * numParms; ++it) { - llvm::StringRef trimmed = it->trim(); - if (needsComma) - specializations.back().first += ", "; - specializations.back().first += trimmed; - needsComma = true; - } - specializations.back().first += '>'; - } - } - foundSpecializations = true; - break; - } - } - } - } - } - - if (!foundSpecializations) { - for (const auto& parent : parentSpecializations) { - if (const clang::NamedDecl* namedDecl = clang::dyn_cast_or_null(decl)) { - if (parent.first.empty()) { - specializations.emplace_back(namedDecl->getName().str(), parent.second); - } else { - specializations.emplace_back(std::string(parent.first).append("::").append(namedDecl->getName().str()), - parent.second); - } - } else { - specializations.push_back(parent); - } - } - } - } - - std::vector> GetNestedTypeSpecializations(const clang::DeclContext* decl) { - std::vector> ret; - RecurseNestedTypeSpecializations(decl, ret); - return ret; - } - - void emitEnumerateFunc(clang::CXXRecordDecl* decl, const std::string& baseDNA) { - std::string templateStmt; - std::string qualTypeStr; - GetNestedTypeName(decl, templateStmt, qualTypeStr); - - fileOut << templateStmt; - fileOut << "template \nvoid " << qualTypeStr << "::Enumerate(typename Op::StreamT& s) {\n"; - - if (baseDNA.size()) - fileOut << " " << baseDNA << "::Enumerate(s);\n"; - - enum class NodeType { Do, DoSeek, DoAlign }; - struct OutputNode { - NodeType m_type = NodeType::Do; - std::string m_fieldName; - std::string m_ioOp; - bool m_squelched = false; - OutputNode(NodeType type, std::string fieldName, std::string ioOp, bool squelched) - : m_type(type), m_fieldName(std::move(fieldName)), m_ioOp(std::move(ioOp)), m_squelched(squelched) {} - }; - std::vector outputNodes; - - for (const clang::FieldDecl* field : decl->fields()) { - clang::QualType qualType = field->getType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (!regType || regType->getTypeClass() == clang::Type::TemplateTypeParm) - continue; - while (regType->getTypeClass() == clang::Type::Elaborated || regType->getTypeClass() == clang::Type::Typedef) - regType = regType->getUnqualifiedDesugaredType(); - - /* Resolve constant array */ - while (regType->getTypeClass() == clang::Type::ConstantArray) { - const auto* caType = static_cast(regType); - qualType = caType->getElementType(); - regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Elaborated) - regType = regType->getUnqualifiedDesugaredType(); - } - - std::string fieldName = field->getName().str(); - std::string propIdExpr = GetPropIdExpr(field, fieldName); - - if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { - const auto* tsType = static_cast(regType); - const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); - const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); - - if (tsDecl->getName() == "Value") { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - /* FIXME: The is the following code required? */ -#if 0 - if (classParms->size() >= 2) { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - const auto* nttParm = static_cast(endianParm); - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } -#endif - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr(); - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - - std::string ioOp; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Type) { - if (defaultEndian) { - ioOp = GetOpString(fieldName, propIdExpr); - } else { - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - } - } - - if (ioOp.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '"s.append(tsDecl->getName().str()).append("' with Athena")); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); - } else if (tsDecl->getName() == "Vector") { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 3) { - const clang::NamedDecl* endianParm = classParms->getParam(2); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - const auto* nttParm = static_cast(endianParm); - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExpr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 1) { - const auto* uExpr = static_cast(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 = static_cast(argExpr)->getSubExpr(); - - if (argExpr->getStmtClass() == clang::Stmt::DeclRefExprClass) { - const auto* drExpr = static_cast(argExpr); - std::string testName = drExpr->getFoundDecl()->getNameAsString(); - for (auto i = outputNodes.rbegin(); i != outputNodes.rend(); ++i) { - if (i->m_fieldName == testName) { - i->m_squelched = true; - break; - } - } - } - llvm::raw_string_ostream strStream2(sizeExpr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } - } else if (idx == 2) { - defaultEndian = false; - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - ++idx; - } - - clang::QualType templateType; - std::string ioOp; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Type) { - templateType = arg.getAsType().getCanonicalType(); - if (defaultEndian) { - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); - } else { - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); - } - } - } - - if (ioOp.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '"s.append(templateType.getAsString()).append("' with Athena")); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - if (sizeExpr.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use count variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); - } else if (tsDecl->getName() == "Buffer") { - const clang::Expr* sizeExpr = nullptr; - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const auto* uExpr = - static_cast(arg.getAsExpr()->IgnoreImpCasts()); - if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - sizeExpr = argExpr; - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - } - if (sizeExprStr.empty()) { - if (sizeExpr) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(sizeExpr->getExprLoc(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(sizeExpr->getSourceRange(), true)); - } else { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - } - continue; - } - - std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); - } else if (tsDecl->getName() == "String") { - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - const auto* uExpr = static_cast(expr); - llvm::APSInt sizeLiteral; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } else if (GetIntegerConstantExpr(expr, sizeLiteral, context)) { -#if LLVM_VERSION_MAJOR >= 13 - llvm::SmallVector strStream; - sizeLiteral.toString(strStream, 10); - sizeExprStr = std::string(strStream.begin(), strStream.end()); -#else - sizeExprStr = sizeLiteral.toString(10); -#endif - } - } - } - - std::string ioOp; - if (!sizeExprStr.empty()) { - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - } else { - ioOp = GetOpString(fieldName, propIdExpr); - } - - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); - } else if (tsDecl->getName() == "WString") { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - const auto* nttParm = static_cast(endianParm); - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExprStr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 0) { - llvm::APSInt sizeLiteral; - const auto* uExpr = static_cast(expr); - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream2(sizeExprStr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } else if (GetIntegerConstantExpr(expr, sizeLiteral, context)) { -#if LLVM_VERSION_MAJOR >= 13 - llvm::SmallVector strStream; - sizeLiteral.toString(strStream, 10); - sizeExprStr = std::string(strStream.begin(), strStream.end()); -#else - sizeExprStr = sizeLiteral.toString(10); -#endif - } - } else if (idx == 1) { - defaultEndian = false; - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - ++idx; - } - - std::string ioOp; - if (!sizeExprStr.empty()) { - if (defaultEndian) { - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - } else { - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); - } - } else { - if (defaultEndian) { - ioOp = GetOpString(fieldName, propIdExpr); - } else { - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - } - - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), std::move(ioOp), false); - } else if (tsDecl->getName() == "Seek") { - size_t idx = 0; - std::string offsetExprStr; - llvm::APSInt direction(64, false); - const clang::Expr* directionExpr = nullptr; - bool bad = false; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (!idx) { - const auto* uExpr = static_cast(expr); - llvm::APSInt offsetLiteral; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream(offsetExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } else if (GetIntegerConstantExpr(expr, offsetLiteral, context)) { -#if LLVM_VERSION_MAJOR >= 13 - llvm::SmallVector strStream; - offsetLiteral.toString(strStream, 10); - offsetExprStr = std::string(strStream.begin(), strStream.end()); -#else - offsetExprStr = offsetLiteral.toString(10); -#endif - } - } else { - clang::APValue result; - if (expr->isCXX11ConstantExpr(context, &result)) { - directionExpr = expr; - direction = result.getInt(); - } else { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getExprLoc(), AthenaError); - diag.AddString("Unable to use non-constant direction expression in Athena"); - diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); - bad = true; - break; - } - } - } - ++idx; - } - if (bad) - continue; - - int64_t directionVal = direction.getSExtValue(); - if (directionVal < 0 || directionVal > 2) { - if (directionExpr) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(directionExpr->getExprLoc(), AthenaError); - diag.AddString("Direction parameter must be 'Begin', 'Current', or 'End'"); - diag.AddSourceRange(clang::CharSourceRange(directionExpr->getSourceRange(), true)); - } else { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Direction parameter must be 'Begin', 'Current', or 'End'"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - } - continue; - } - - if (directionVal == 0) { - outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), - "("s.append(offsetExprStr).append(", athena::SeekOrigin::Begin, s)"), false); - } else if (directionVal == 1) { - outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), - "("s.append(offsetExprStr).append(", athena::SeekOrigin::Current, s)"), false); - } else if (directionVal == 2) { - outputNodes.emplace_back(NodeType::DoSeek, std::move(fieldName), - "("s.append(offsetExprStr).append(", athena::SeekOrigin::End, s)"), false); - } - } else if (tsDecl->getName() == "Align") { - llvm::APSInt align(64, 0); - bool bad = false; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr(); - if (!GetIntegerConstantExpr(expr, align, context)) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(expr->getExprLoc(), AthenaError); - diag.AddString("Unable to use non-constant align expression in Athena"); - diag.AddSourceRange(clang::CharSourceRange(expr->getSourceRange(), true)); - bad = true; - break; - } - } - } - if (bad) - continue; - - const int64_t alignVal = align.getSExtValue(); - if (alignVal) { -#if LLVM_VERSION_MAJOR >= 13 - llvm::SmallVector alignStream; - align.toString(alignStream, 10, true); - outputNodes.emplace_back(NodeType::DoAlign, std::move(fieldName), - "("s.append(alignStream.begin(), alignStream.end()).append(", s)"), false); -#else - outputNodes.emplace_back(NodeType::DoAlign, std::move(fieldName), - "("s.append(align.toString(10, true)).append(", s)"), false); -#endif - } - } else { - const clang::NamedDecl* nd = tsDecl->getTemplatedDecl(); - if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null(nd)) { - std::string baseDNA2; - if (isDNARecord(rd, baseDNA2)) { - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), GetOpString(fieldName, propIdExpr), false); - } - } - } - } else if (regType->getTypeClass() == clang::Type::Record) { - const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - std::string baseDNA2; - if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) { - outputNodes.emplace_back(NodeType::Do, std::move(fieldName), GetOpString(fieldName, propIdExpr), false); - } - } - } - - for (const OutputNode& node : outputNodes) { - switch (node.m_type) { - case NodeType::Do: - if (node.m_squelched) - fileOut << " DoSize" << node.m_ioOp << ";\n"; - else - fileOut << " Do" << node.m_ioOp << ";\n"; - break; - case NodeType::DoSeek: - fileOut << " DoSeek" << node.m_ioOp << ";\n"; - break; - case NodeType::DoAlign: - fileOut << " DoAlign" << node.m_ioOp << ";\n"; - break; - } - } - - fileOut << "}\n\n"; - } - - void emitLookupFunc(clang::CXXRecordDecl* decl, const std::string& baseDNA) { - std::string templateStmt; - std::string qualTypeStr; - GetNestedTypeName(decl, templateStmt, qualTypeStr); - - fileOut << templateStmt; - fileOut << "template \nbool " << qualTypeStr << "::Lookup(uint64_t hash, typename Op::StreamT& s) {\n"; - - if (baseDNA.size()) - fileOut << " if (" << baseDNA << "::Lookup(hash, s))\n" - << " return true;\n"; - - fileOut << " switch (hash) {\n"; - - for (const clang::FieldDecl* field : decl->fields()) { - clang::QualType qualType = field->getType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (!regType || regType->getTypeClass() == clang::Type::TemplateTypeParm) - continue; - while (regType->getTypeClass() == clang::Type::Elaborated || regType->getTypeClass() == clang::Type::Typedef) - regType = regType->getUnqualifiedDesugaredType(); - - /* Resolve constant array */ - while (regType->getTypeClass() == clang::Type::ConstantArray) { - const auto* caType = static_cast(regType); - qualType = caType->getElementType(); - regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Elaborated) - regType = regType->getUnqualifiedDesugaredType(); - } - - std::string fieldName = field->getName().str(); - std::string propIdExpr = GetPropIdExpr(field, fieldName); - - if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { - const auto* tsType = static_cast(regType); - const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); - const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); - - if (tsDecl->getName() == "Value") { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - const auto* nttParm = static_cast(endianParm); - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr(); - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - - std::string ioOp; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Type) { - if (defaultEndian) - ioOp = GetOpString(fieldName, propIdExpr); - else - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - } - - if (ioOp.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '"s.append(tsDecl->getName().str()).append("' with Athena")); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - - } else if (tsDecl->getName() == "Vector") { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 3) { - const clang::NamedDecl* endianParm = classParms->getParam(2); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - const auto* nttParm = static_cast(endianParm); - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExpr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 1) { - const auto* uExpr = static_cast(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 = static_cast(argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream2(sizeExpr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } - } else if (idx == 2) { - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - ++idx; - } - - clang::QualType templateType; - std::string ioOp; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Type) { - templateType = arg.getAsType().getCanonicalType(); - if (defaultEndian) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr); - else - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExpr, endianExprStr); - } - } - - if (ioOp.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use type '"s.append(templateType.getAsString()).append("' with Athena")); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - if (sizeExpr.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use count variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - continue; - } - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } else if (tsDecl->getName() == "Buffer") { - const clang::Expr* sizeExpr = nullptr; - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const auto* uExpr = - static_cast(arg.getAsExpr()->IgnoreImpCasts()); - if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - sizeExpr = argExpr; - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } - } - } - if (sizeExprStr.empty()) { - if (sizeExpr) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(sizeExpr->getExprLoc(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(sizeExpr->getSourceRange(), true)); - } else { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(field->getLocation(), AthenaError); - diag.AddString("Unable to use size variable with Athena"); - diag.AddSourceRange(clang::CharSourceRange(field->getSourceRange(), true)); - } - continue; - } - - std::string ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } else if (tsDecl->getName() == "String") { - std::string sizeExprStr; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - const auto* uExpr = static_cast(expr); - llvm::APSInt sizeLiteral; - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream(sizeExprStr); - argExpr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - } else if (GetIntegerConstantExpr(expr, sizeLiteral, context)) { -#if LLVM_VERSION_MAJOR >= 13 - llvm::SmallVector strStream; - sizeLiteral.toString(strStream, 10); - sizeExprStr = std::string(strStream.begin(), strStream.end()); -#else - sizeExprStr = sizeLiteral.toString(10); -#endif - } - } - } - - std::string ioOp; - if (!sizeExprStr.empty()) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else - ioOp = GetOpString(fieldName, propIdExpr); - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } else if (tsDecl->getName() == "WString") { - llvm::APSInt endian(64, -1); - std::string endianExprStr; - bool defaultEndian = true; - if (classParms->size() >= 2) { - const clang::NamedDecl* endianParm = classParms->getParam(1); - if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) { - const auto* nttParm = static_cast(endianParm); - llvm::raw_string_ostream strStream(endianExprStr); - nttParm->print(strStream, context.getPrintingPolicy()); - } - } - - std::string sizeExprStr; - size_t idx = 0; - for (const clang::TemplateArgument& arg : *tsType) { - if (arg.getKind() == clang::TemplateArgument::Expression) { - const clang::Expr* expr = arg.getAsExpr()->IgnoreImpCasts(); - if (idx == 0) { - llvm::APSInt sizeLiteral; - const auto* uExpr = static_cast(expr); - if (expr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && - uExpr->getKind() == clang::UETT_SizeOf) { - const clang::Expr* argExpr = uExpr->getArgumentExpr(); - while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) - argExpr = static_cast(argExpr)->getSubExpr(); - llvm::raw_string_ostream strStream2(sizeExprStr); - argExpr->printPretty(strStream2, nullptr, context.getPrintingPolicy()); - } else if (GetIntegerConstantExpr(expr, sizeLiteral, context)) { -#if LLVM_VERSION_MAJOR >= 13 - llvm::SmallVector strStream; - sizeLiteral.toString(strStream, 10); - sizeExprStr = std::string(strStream.begin(), strStream.end()); -#else - sizeExprStr = sizeLiteral.toString(10); -#endif - } - } else if (idx == 1) { - llvm::raw_string_ostream strStream(endianExprStr); - expr->printPretty(strStream, nullptr, context.getPrintingPolicy()); - defaultEndian = false; - } - } - ++idx; - } - - std::string ioOp; - if (!sizeExprStr.empty()) { - if (defaultEndian) - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr); - else - ioOp = GetVectorOpString(fieldName, propIdExpr, sizeExprStr, endianExprStr); - } else { - if (defaultEndian) - ioOp = GetOpString(fieldName, propIdExpr); - else - ioOp = GetOpString(fieldName, propIdExpr, endianExprStr); - } - - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << ioOp << ";\n" - << " return true;\n"; - } else { - const clang::NamedDecl* nd = tsDecl->getTemplatedDecl(); - if (const clang::CXXRecordDecl* rd = clang::dyn_cast_or_null(nd)) { - std::string baseDNA2; - if (isDNARecord(rd, baseDNA2)) { - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" - << " return true;\n"; - } - } - } - } else if (regType->getTypeClass() == clang::Type::Record) { - const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); - std::string baseDNA2; - if (cxxRDecl && isDNARecord(cxxRDecl, baseDNA2)) { - fileOut << " AT_PROP_CASE(" << propIdExpr << "):\n" - << " Do" << GetOpString(fieldName, propIdExpr) << ";\n" - << " return true;\n"; - } - } - } - - fileOut << " default:\n return false;\n }\n}\n\n"; - } - -public: - explicit ATDNAEmitVisitor(clang::ASTContext& ctxin, StreamOut& fo) : context(ctxin), fileOut(fo) {} - - bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) { - if (!EmitIncludes && !context.getSourceManager().isInMainFile(decl->getLocation())) - return true; - - if (decl->isInvalidDecl() || !decl->hasDefinition() || !decl->isCompleteDefinition()) - return true; - - if (!decl->getNumBases()) - return true; - - /* First ensure this inherits from struct athena::io::DNA */ - std::string baseDNA; - if (!isDNARecord(decl, baseDNA)) - return true; - - /* Determine if is is a YAML DNA */ - bool isYamlDNA = false; - for (const clang::CXXMethodDecl* method : decl->methods()) - if (method->getDeclName().isIdentifier() && (method->getName() == "read" || method->getName() == "write") && - method->getNumParams() == 1 && - method->getParamDecl(0)->getType().getAsString() == "athena::io::YAMLDocReader &") { - isYamlDNA = true; - break; - } - - /* Determine if this is a regular DNA or PropDNA */ - bool isPropDNA = false; - for (const clang::Decl* d : decl->decls()) - if (const clang::FunctionTemplateDecl* m = clang::dyn_cast_or_null(d)) - if (m->getDeclName().isIdentifier() && m->getName() == "Lookup") { - isPropDNA = true; - break; - } - - /* Make sure there isn't Delete meta type */ - for (const clang::FieldDecl* field : decl->fields()) { - clang::QualType qualType = field->getType().getCanonicalType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (regType) { - const clang::CXXRecordDecl* rDecl = regType->getAsCXXRecordDecl(); - if (rDecl) { - if (rDecl->getName() == "Delete") { - const clang::CXXRecordDecl* rParentDecl = llvm::dyn_cast_or_null(rDecl->getParent()); - if (rParentDecl) { - std::string parentCheck = rParentDecl->getTypeForDecl()->getCanonicalTypeInternal().getAsString(); - if (!parentCheck.compare(0, sizeof(ATHENA_DNA_BASETYPE) - 1, ATHENA_DNA_BASETYPE)) - return true; - } - } - } - } - } - - std::vector> specializations = GetNestedTypeSpecializations(decl); - - emitEnumerateFunc(decl, baseDNA); - if (isPropDNA) { - emitLookupFunc(decl, baseDNA); - for (const auto& specialization : specializations) - fileOut << "AT_SPECIALIZE_PROPDNA(" << specialization.first << ")\n"; - } else if (isYamlDNA) { - for (const auto& specialization : specializations) - fileOut << "AT_SPECIALIZE_DNA_YAML(" << specialization.first << ")\n"; - } else { - for (const auto& specialization : specializations) - fileOut << "AT_SPECIALIZE_DNA(" << specialization.first << ")\n"; - } - fileOut << "\n\n"; - - for (const auto& specialization : specializations) { - for (int i = 0; i < specialization.second; ++i) - fileOut << "template <>\n"; - fileOut << "std::string_view " << specialization.first << "::DNAType() {\n return \"" << specialization.first - << "\"sv;\n}\n"; - } - fileOut << "\n\n"; - - return true; - } -}; - -class ATDNAConsumer : public clang::ASTConsumer { - std::unique_ptr fileOut; - StreamOut& fileOutOld; - ATDNAEmitVisitor emitVisitor; - -public: - explicit ATDNAConsumer(clang::ASTContext& context, std::unique_ptr&& fo, StreamOut* foOld) - : fileOut(std::move(fo)), fileOutOld(*foOld), emitVisitor(context, *foOld) {} - - void HandleTranslationUnit(clang::ASTContext& context) override { - /* Write file head */ - fileOutOld << "/* Auto generated atdna implementation */\n" - "#include \"athena/DNAOp.hpp\"\n"; - for (const std::string& inputf : InputFilenames) - fileOutOld << "#include \"" << inputf << "\"\n"; - fileOutOld << "\n"; - - /* Emit file */ - emitVisitor.TraverseDecl(context.getTranslationUnitDecl()); - } -}; - -class ATDNAAction : public clang::ASTFrontendAction { - /* Used by LLVM 3.9+; client owns stream */ - std::unique_ptr MakeStreamOut(std::unique_ptr&& so, StreamOut*& outPtr) { - outPtr = so.get(); - return std::move(so); - } - - /* Used by previous versions of LLVM; CompilerInstance owns stream */ - std::unique_ptr MakeStreamOut(StreamOut* so, StreamOut*& outPtr) { - outPtr = so; - return {}; - } - -#if LLVM_VERSION_MAJOR >= 9 - llvm::Optional TheDependencyFileGenerator; -#else - std::unique_ptr TheDependencyFileGenerator; -#endif - -public: - explicit ATDNAAction() = default; - std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, - llvm::StringRef /*filename*/) override { - clang::DependencyOutputOptions DepOpts; - DepOpts.OutputFile = DepFileOut.getValue(); - DepOpts.Targets = DepFileTargets; -#if LLVM_VERSION_MAJOR >= 9 - if (!DepOpts.OutputFile.empty()) { - TheDependencyFileGenerator.emplace(DepOpts); - TheDependencyFileGenerator->attachToPreprocessor(compiler.getPreprocessor()); - } -#else - if (!DepOpts.OutputFile.empty()) - TheDependencyFileGenerator.reset( - clang::DependencyFileGenerator::CreateAndAttachToPreprocessor(compiler.getPreprocessor(), DepOpts)); -#endif - - std::unique_ptr fileout; - StreamOut* fileoutOld; - if (OutputFilename.size()) -#if LLVM_VERSION_MAJOR >= 12 - fileout = MakeStreamOut(compiler.createOutputFile(OutputFilename, false, true, true), fileoutOld); -#else - fileout = MakeStreamOut(compiler.createOutputFile(OutputFilename, false, true, "", "", true), fileoutOld); -#endif - else - fileout = MakeStreamOut(compiler.createDefaultOutputFile(false, "a", "cpp"), fileoutOld); - AthenaError = - compiler.getASTContext().getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Athena error: %0"); - return std::unique_ptr( - new ATDNAConsumer(compiler.getASTContext(), std::move(fileout), fileoutOld)); - } -}; - -int main(int argc, const char** argv) { - llvm::cl::ParseCommandLineOptions(argc, argv, "Athena DNA Generator"); - if (Help) - llvm::cl::PrintHelpMessage(); - - std::vector args = { - XSTR(ATDNA_ARGV0), - "-fsyntax-only", - "-std=c++2a", -#if __x86_64__ - "-mno-sse", -#endif - "-D__atdna__=1", - "-Wno-expansion-to-defined", - "-Wno-nullability-completeness", - "-Werror=shadow-field", - "-I" XSTR(INSTALL_PREFIX) "/include/Athena", - }; - for (int a = 1; a < argc; ++a) { - args.emplace_back(argv[a]); - } - - llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); -#if LLVM_VERSION_MAJOR >= 10 - clang::tooling::ToolInvocation TI(std::move(args), std::make_unique(), fman.get()); -#else - ATDNAAction* action = new ATDNAAction(); - clang::tooling::ToolInvocation TI(std::move(args), action, fman.get()); -#endif - if (!TI.run()) - return 1; - return 0; -} diff --git a/atdna/main.rc.in b/atdna/main.rc.in deleted file mode 100644 index 601f2af..0000000 --- a/atdna/main.rc.in +++ /dev/null @@ -1,32 +0,0 @@ -#include "winver.h" - -IDI_ICON1 ICON DISCARDABLE "@ATHENA_ICO@" - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @ATHENA_MAJOR_VERSION@,@ATHENA_MINOR_VERSION@,@ATHENA_PATCH_VERSION@,0 - PRODUCTVERSION @ATHENA_MAJOR_VERSION@,@ATHENA_MINOR_VERSION@,@ATHENA_PATCH_VERSION@,0 - FILEFLAGS 0x0L - FILEFLAGSMASK 0x3fL - FILEOS 0x00040004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "CompanyName", "Jackoalan / Antidote" - VALUE "FileDescription", "ATDNA" - VALUE "FileVersion", "@ATHENA_VERSION@" - VALUE "LegalCopyright", "Copyright (C) 2016 Jackoalan / Antidote" - VALUE "InternalName", "atdna" - VALUE "OriginalFilename", "atdna.exe" - VALUE "ProductName", "ATDNA" - VALUE "ProductVersion", "@ATHENA_VERSION@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END diff --git a/atdna/test.cpp b/atdna/test.cpp deleted file mode 100644 index 7137acd..0000000 --- a/atdna/test.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "test.hpp" - -#include -#include - -#define EXPECTED_BYTES 281 - -int main(int argc, const char** argv) { - TESTFile file = {}; - file.arrCount[0] = 2; - file.array.push_back(42); - file.array.push_back(64); - size_t binSize = 0; - file.binarySize(binSize); - athena::io::MemoryCopyWriter w(nullptr, binSize); - atInt64 pos = w.position(); - file.write(w); - - const bool pass = !w.hasError() && w.position() - pos == binSize && binSize == EXPECTED_BYTES; - if (pass) { - fmt::print(FMT_STRING("[PASS] {} bytes written\n"), size_t(w.position() - pos)); - } else { - fmt::print(FMT_STRING("[FAIL] {} bytes written; {} bytes sized; {} bytes expected\n"), size_t(w.position() - pos), binSize, - EXPECTED_BYTES); - } - - return pass ? 0 : 1; -} diff --git a/atdna/test.hpp b/atdna/test.hpp deleted file mode 100644 index f92d211..0000000 --- a/atdna/test.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#include - -using namespace athena; -typedef io::DNA BigDNA; - -enum ETest : atUint8 { ZERO, ONE, TWO, THREE }; - -template -struct AT_SPECIALIZE_PARMS(ETest::ZERO, ETest::ONE, ETest::TWO, ETest::THREE) TESTSubFile : public BigDNA { - AT_DECL_DNA - Value varE = EVal; - Value sub1; - Value sub2; -}; - -struct TESTSubClassFile : public TESTSubFile { - AT_DECL_DNA - Value sub3; - Value sub4; -}; - -struct TESTSubSubClassFile : public TESTSubClassFile { - AT_DECL_DNA - Value sub5; - Value sub6; -}; - -template -struct AT_SPECIALIZE_PARMS(atUint16, 42, atUint32, 87, atUint32, 2) TESTFile : public BigDNA { - AT_DECL_DNA - Value varBool; - AT_OVERRIDE_RCRC32(12345678) Value x4_var32 = Var32Val; - AT_OVERRIDE_RCRC32(deadbabe) Value x8_var16; - Value vec3; - Value vec4; - - struct TESTNestedSubFile : public BigDNA { - AT_DECL_DNA - Value nestSub1; - Value nestSub2; - } nestedSubFile; - - using TESTSubFileUsing = TESTSubFile; - TESTSubFileUsing subFile; - - Align<4> align; - - template - struct AT_SPECIALIZE_PARMS(atInt32, 36, atInt64, 96) TESTTemplateSubFile : public BigDNA { - AT_DECL_DNA - Value explSub1 = NestedVal; - Value explSub2 = Var32Val; - }; - Value> nestedTemplate1; - Value> nestedTemplate2; - - Value arrCount[2]; - Vector array; - - Value arrAltCount; - Vector arrayAlt; - - Seek<21, SeekOrigin::Current> seek; - - Value arrCount2; - Vector, AT_DNA_COUNT(arrCount[1] + arrCount2)> array2; - - Value bufSz; - Buffer buf; - - String<32> str; - WString<64> wstr; -}; diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index e5dbc45..d1a18ab 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -1,14 +1,8 @@ -add_subdirectory(lzokay) -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - target_compile_options(lzokay PRIVATE -Wno-maybe-uninitialized) +if (EXISTS ${CMAKE_SOURCE_DIR}/extern/lzokay) + add_subdirectory(lzokay) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(lzokay PRIVATE -Wno-maybe-uninitialized) + endif () endif () add_subdirectory(zlib) -add_subdirectory(yaml) -if(NOT TARGET fmt) - add_subdirectory(fmt) - target_compile_definitions(fmt PUBLIC - FMT_ARM_ABI_COMPATIBILITY=1 - FMT_EXCEPTIONS=0) - target_compile_definitions(fmt INTERFACE - FMT_ENFORCE_COMPILE_STRING=1) -endif() \ No newline at end of file +add_subdirectory(yaml) \ No newline at end of file diff --git a/extern/fmt b/extern/fmt deleted file mode 160000 index 9e8b86f..0000000 --- a/extern/fmt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9e8b86fd2d9806672cc73133d21780dd182bfd24 diff --git a/extern/lzokay b/extern/lzokay index ee8b4c2..db2df1f 160000 --- a/extern/lzokay +++ b/extern/lzokay @@ -1 +1 @@ -Subproject commit ee8b4c29ad0fabcaa210962e30c081d05e55e2b3 +Subproject commit db2df1fcbebc2ed06c10f727f72567d40f06a2be diff --git a/include/athena/DNA.hpp b/include/athena/DNA.hpp deleted file mode 100644 index 887054b..0000000 --- a/include/athena/DNA.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once - -/* BIG FAT WARNING!!! - * - * The type-structure of this file is expected to remain consistent for 'atdna' - * Any changes to the types or namespacing must be reflected in 'atdna/main.cpp' - */ - -#include -#include -#include - -#include - -#include "athena/DNAOp.hpp" -#include "athena/Global.hpp" -#include "athena/IStreamReader.hpp" -#include "athena/IStreamWriter.hpp" - -using namespace std::literals; - -namespace athena::io { - -/** - * @brief Base DNA class used against 'atdna' - * @tparam DNAE Default-endianness for contained DNA values - * - * Athena bundles a build-tool called 'atdna'. This tool functions - * just like the 'clang' compiler, except it emits a full .cpp implementation - * with all read/write calls necessary to marshal the DNA structure to/from - * a streamed medium - */ -template -struct DNA { - /** - * @brief Designated byte-order used for serializing fields - */ - static constexpr Endian DNAEndian = DNAE; - - /** - * @brief Template type signaling atdna to capture the value where it's used - * @tparam T The type of the value. Can be any numeric type or atVec* type - * @tparam VE Endianness of the value - */ - template - using Value = T; - - /** - * @brief Template type wrapping std::vector and signaling atdna to manipulate it where it's used - * @tparam T The type of contained elements. Can be any numeric type, atVec* type, or another DNA subclass - * @tparam cntVar C++ expression wrapped in DNA_COUNT macro to determine number of elements for vector - * @tparam VE Endianness of the contained values - */ - template - using Vector = std::vector; - - /** - * @brief Template type wrapping std::unique_ptr and signaling atdna to read a - * raw byte-buffer where it's used - * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of bytes for buffer - */ - template - using Buffer = std::unique_ptr; - - /** - * @brief Template type wrapping std::string and signaling atdna to read string data where it's used - * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string - * -1 literal indicates null-terminated string - */ - template - using String = std::string; - - /** - * @brief Template type wrapping std::wstring and signaling atdna to read wstring data where it's used - * @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for wstring - * -1 literal indicates null-terminated wstring - */ - template - using WString = std::wstring; - - /** - * @brief Meta Template signaling atdna to insert a stream seek where it's used - * @tparam offset C++ expression wrapped in DNA_COUNT macro to determine number of bytes to seek - * @tparam direction SeekOrigin to seek relative to - */ - template - struct Seek {}; - - /** - * @brief Meta Template signaling atdna to insert an aligning stream seek where it's used - * @tparam align Number of bytes to align to - */ - template - struct Align {}; - - /** - * @brief Meta Template preventing atdna from emitting read/write implementations - */ - struct Delete {}; - - /* Bring fundamental operations into DNA subclasses for easier per-op overrides */ - using Read = athena::io::Read; - using Write = athena::io::Write; - using BinarySize = athena::io::BinarySize; - using PropCount = athena::io::PropCount; - using ReadYaml = athena::io::ReadYaml; - using WriteYaml = athena::io::WriteYaml; -}; - -/** - * @brief Virtual DNA wrapper for subclasses that utilize virtual method calls - * @tparam DNAE Default-endianness for contained DNA values - * - * Typically, static template-based DNA resolution is sufficient; however, formats - * with a tree of variously-typed data structures would benefit from having a vtable. - * - * Note: It's not recommended to implement these directly. Instead, use the AT_DECL_DNA or - * AT_DECL_EXPLCIT_DNA macro in the subclasses. Specializing the Enumerate method - * is the proper way to override individual I/O operations. Owners of the virtualized - * subclass will typically use a unique_ptr to reference the data; specializing their own - * Enumerate methods as such: - * - * template <> void MySubclass::Enumerate(typename Read::StreamT& r) - * { (Do stuff with `r`) } - */ -template -struct DNAV : DNA { - virtual ~DNAV() = default; - virtual void read(athena::io::IStreamReader& r) = 0; - virtual void write(athena::io::IStreamWriter& w) const = 0; - virtual void binarySize(size_t& s) const = 0; - virtual std::string_view DNATypeV() const = 0; -}; - -template -struct DNAVYaml : DNAV { - virtual ~DNAVYaml() = default; - void read(athena::io::IStreamReader& r) override = 0; - void write(athena::io::IStreamWriter& w) const override = 0; - void binarySize(size_t& s) const override = 0; - virtual void read(athena::io::YAMLDocReader& r) = 0; - virtual void write(athena::io::YAMLDocWriter& w) const = 0; -}; - -/** Macro to supply count variable to atdna and mute it for other compilers */ -#ifdef __clang__ -#define AT_DNA_COUNT(...) sizeof(__VA_ARGS__) -#else -#define AT_DNA_COUNT(...) 0 -#endif - -} // namespace athena::io diff --git a/include/athena/DNAOp.hpp b/include/athena/DNAOp.hpp deleted file mode 100644 index abb651f..0000000 --- a/include/athena/DNAOp.hpp +++ /dev/null @@ -1,1187 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "athena/ChecksumsLiterals.hpp" -#include "athena/IStreamReader.hpp" -#include "athena/IStreamWriter.hpp" -#include "athena/YAMLDocReader.hpp" -#include "athena/YAMLDocWriter.hpp" - -namespace athena::io { - -struct PropId { - std::string_view name; - uint32_t rcrc32 = 0xffffffff; - uint64_t crc64 = 0x0; - template - constexpr T opget() const; - constexpr PropId() = default; - constexpr explicit PropId(std::string_view name, uint32_t rcrc32, uint64_t crc64) - : name(name), rcrc32(rcrc32), crc64(crc64) {} - constexpr explicit PropId(std::string_view name) - : name(name) - , rcrc32(athena::checksums::literals::rcrc32_rec(0xFFFFFFFF, name.data())) - , crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name.data())) {} - constexpr PropId(std::string_view name, uint32_t rcrc32) - : name(name), rcrc32(rcrc32), crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name.data())) {} -}; - -template <> -constexpr uint32_t PropId::opget() const { - return rcrc32; -} - -template <> -constexpr uint64_t PropId::opget() const { - return crc64; -} - -namespace literals { -constexpr PropId operator"" _propid(const char* s, size_t len) { return PropId{s}; } -} // namespace literals - -#define AT_PROP_CASE(...) case athena::io::PropId(__VA_ARGS__).opget() - -#if defined(__atdna__) -#define AT_OVERRIDE_RCRC32(rcrc32) __attribute__((annotate("rcrc32=" #rcrc32))) -#else -#define AT_OVERRIDE_RCRC32(rcrc32) -#endif - -#if defined(__atdna__) -#define AT_SPECIALIZE_PARMS(...) __attribute__((annotate("specparms=" #__VA_ARGS__))) -#else -#define AT_SPECIALIZE_PARMS(...) -#endif - -enum class PropType { None, CRC32, CRC64 }; - -template -using __IsPODType = std::disjunction< - std::is_arithmetic>, std::is_convertible&, atVec2f&>, - std::is_convertible&, atVec3f&>, std::is_convertible&, atVec4f&>, - std::is_convertible&, atVec2d&>, std::is_convertible&, atVec3d&>, - std::is_convertible&, atVec4d&>>; -template -constexpr bool __IsPODType_v = __IsPODType::value; - -template -using __CastPODType = std::conditional_t< - std::is_convertible_v&, atVec2f&>, atVec2f, - std::conditional_t< - std::is_convertible_v&, atVec3f&>, atVec3f, - std::conditional_t< - std::is_convertible_v&, atVec4f&>, atVec4f, - std::conditional_t< - std::is_convertible_v&, atVec2d&>, atVec2d, - std::conditional_t&, atVec3d&>, atVec3d, - std::conditional_t&, atVec4d&>, atVec4d, - std::remove_cv_t>>>>>>; - -template -uint16_t __Read16(IStreamReader& r) { - return DNAE == Endian::Big ? r.readUint16Big() : r.readUint16Little(); -} - -template -void __Write16(IStreamWriter& w, uint16_t v) { - DNAE == Endian::Big ? w.writeUint16Big(v) : w.writeUint16Little(v); -} - -template -uint32_t __Read32(IStreamReader& r) { - return DNAE == Endian::Big ? r.readUint32Big() : r.readUint32Little(); -} - -template -void __Write32(IStreamWriter& w, uint32_t v) { - DNAE == Endian::Big ? w.writeUint32Big(v) : w.writeUint32Little(v); -} - -template -uint64_t __Read64(IStreamReader& r) { - return DNAE == Endian::Big ? r.readUint64Big() : r.readUint64Little(); -} - -template -void __Write64(IStreamWriter& w, uint64_t v) { - DNAE == Endian::Big ? w.writeUint64Big(v) : w.writeUint64Little(v); -} - -template -struct BinarySize { - using PropT = std::conditional_t; - using StreamT = size_t; - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { - if (PropOp != PropType::None) { - /* Accessed via Enumerate, header */ - s += 6; - } - using PODType = std::underlying_type_t; - BinarySize::Do(id, *reinterpret_cast(&var), s); - } - template - static std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& s) { - if (PropOp != PropType::None) { - /* Accessed via Enumerate, header */ - s += 6; - } - using CastT = __CastPODType; - BinarySize::Do(id, static_cast(const_cast&>(var)), s); - } - template - static std::enable_if_t<__IsDNARecord_v && PropOp != PropType::None> Do(const PropId& id, T& var, StreamT& s) { - /* Accessed via Enumerate, header */ - s += 6; - var.template Enumerate>(s); - } - template - static std::enable_if_t<__IsDNARecord_v && PropOp == PropType::None> Do(const PropId& id, T& var, StreamT& s) { - var.template Enumerate>(s); - } - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { - for (auto& v : var) { - BinarySize::template Do, DNAE>(id, v, s); - } - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) { - BinarySize::template Do(id, var, s); - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& s) { - for (T& v : vector) { - BinarySize::template Do(id, v, s); - } - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& s) { - /* libc++ specializes vector as a bitstream */ - s += vector.size(); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& s) { - if (buf) - s += count; - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { - s += str.size() + 1; - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) { - if (count < 0) - s += str.size() + 1; - else - s += count; - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { - s += str.size() * 2 + 2; - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) { - if (count < 0) - s += str.size() * 2 + 2; - else - s += count * 2; - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) { - switch (whence) { - case SeekOrigin::Begin: - s = amount; - break; - case SeekOrigin::Current: - s += amount; - break; - default: - break; - } - } - static void DoAlign(atInt64 amount, StreamT& s) { s = (s + amount - 1) / amount * amount; } -}; -#define __BINARY_SIZE_S(type, endian) \ - template <> \ - template <> \ - inline void BinarySize::Do(const PropId& id, type& var, BinarySize::StreamT& s) -__BINARY_SIZE_S(bool, Endian::Big) { s += 1; } -__BINARY_SIZE_S(atInt8, Endian::Big) { s += 1; } -__BINARY_SIZE_S(atUint8, Endian::Big) { s += 1; } -__BINARY_SIZE_S(atInt16, Endian::Big) { s += 2; } -__BINARY_SIZE_S(atUint16, Endian::Big) { s += 2; } -__BINARY_SIZE_S(atInt32, Endian::Big) { s += 4; } -__BINARY_SIZE_S(atUint32, Endian::Big) { s += 4; } -__BINARY_SIZE_S(atInt64, Endian::Big) { s += 8; } -__BINARY_SIZE_S(atUint64, Endian::Big) { s += 8; } -__BINARY_SIZE_S(float, Endian::Big) { s += 4; } -__BINARY_SIZE_S(double, Endian::Big) { s += 8; } -__BINARY_SIZE_S(atVec2f, Endian::Big) { s += 8; } -__BINARY_SIZE_S(atVec2d, Endian::Big) { s += 16; } -__BINARY_SIZE_S(atVec3f, Endian::Big) { s += 12; } -__BINARY_SIZE_S(atVec3d, Endian::Big) { s += 24; } -__BINARY_SIZE_S(atVec4f, Endian::Big) { s += 16; } -__BINARY_SIZE_S(atVec4d, Endian::Big) { s += 32; } -__BINARY_SIZE_S(bool, Endian::Little) { s += 1; } -__BINARY_SIZE_S(atInt8, Endian::Little) { s += 1; } -__BINARY_SIZE_S(atUint8, Endian::Little) { s += 1; } -__BINARY_SIZE_S(atInt16, Endian::Little) { s += 2; } -__BINARY_SIZE_S(atUint16, Endian::Little) { s += 2; } -__BINARY_SIZE_S(atInt32, Endian::Little) { s += 4; } -__BINARY_SIZE_S(atUint32, Endian::Little) { s += 4; } -__BINARY_SIZE_S(atInt64, Endian::Little) { s += 8; } -__BINARY_SIZE_S(atUint64, Endian::Little) { s += 8; } -__BINARY_SIZE_S(float, Endian::Little) { s += 4; } -__BINARY_SIZE_S(double, Endian::Little) { s += 8; } -__BINARY_SIZE_S(atVec2f, Endian::Little) { s += 8; } -__BINARY_SIZE_S(atVec2d, Endian::Little) { s += 16; } -__BINARY_SIZE_S(atVec3f, Endian::Little) { s += 12; } -__BINARY_SIZE_S(atVec3d, Endian::Little) { s += 24; } -__BINARY_SIZE_S(atVec4f, Endian::Little) { s += 16; } -__BINARY_SIZE_S(atVec4d, Endian::Little) { s += 32; } - -template -struct PropCount { - using PropT = std::conditional_t; - using StreamT = size_t; - template - static void Do(const PropId& id, T& var, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) { - PropCount::template Do(id, var, s); - } - template - static void Do(const PropId& id, std::vector& vector, const S& count, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) { - /* Only reports one level of properties */ - s += 1; - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) {} - static void DoAlign(atInt64 amount, StreamT& s) {} -}; - -template -struct Read { - using PropT = std::conditional_t; - using StreamT = IStreamReader; - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& r) { - using PODType = std::underlying_type_t; - Read::Do(id, *reinterpret_cast(&var), r); - } - template - static std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& r) { - using CastT = __CastPODType; - Read::Do(id, static_cast(var), r); - } - template - static std::enable_if_t<__IsDNARecord() && PropOp == PropType::None> Do(const PropId& id, T& var, StreamT& r) { - var.template Enumerate>(r); - } - template - static std::enable_if_t<__IsDNARecord() && PropOp != PropType::None> Do(const PropId& id, T& var, StreamT& r) { - /* Accessed via Lookup, no header */ - atUint16 propCount = __Read16(r); - for (atUint32 i = 0; i < propCount; ++i) { - atUint64 hash; - if (PropOp == PropType::CRC64) - hash = __Read64(r); - else - hash = __Read32(r); - atInt64 size = __Read16(r); - atInt64 start = r.position(); - var.template Lookup>(hash, r); - atInt64 actualRead = r.position() - start; - if (actualRead != size) - r.seek(size - actualRead); - } - } - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { - for (auto& v : var) { - Read::template Do, DNAE>(id, v, s); - } - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) { - Read::template Do(id, var, s); - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& r) { - vector.clear(); - vector.reserve(count); - for (size_t i = 0; i < static_cast(count); ++i) { - vector.emplace_back(); - Read::template Do(id, vector.back(), r); - } - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& r) { - /* libc++ specializes vector as a bitstream */ - vector.clear(); - vector.reserve(count); - for (size_t i = 0; i < count; ++i) - vector.push_back(r.readBool()); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& r) { - buf.reset(new atUint8[count]); - r.readUBytesToBuf(buf.get(), count); - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { - str = r.readString(); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) { str = r.readString(count); } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { - Read::Do(id, str, r); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) { - Read::Do(id, str, count, r); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) { r.seek(amount, whence); } - static void DoAlign(atInt64 amount, StreamT& r) { - r.seek((r.position() + amount - 1) / amount * amount, athena::SeekOrigin::Begin); - } -}; -#define __READ_S(type, endian) \ - template <> \ - template <> \ - inline void Read::Do(const PropId& id, type& var, Read::StreamT& r) -#define __READ_WSTR_S(endian) \ - template <> \ - template <> \ - inline void Read::Do(const PropId& id, std::wstring& str, Read::StreamT& r) -#define __READ_WSTRC_S(endian) \ - template <> \ - template <> \ - inline void Read::Do(const PropId& id, std::wstring& str, atInt32 count, Read::StreamT& r) -__READ_S(bool, Endian::Big) { var = r.readBool(); } -__READ_S(atInt8, Endian::Big) { var = r.readByte(); } -__READ_S(atUint8, Endian::Big) { var = r.readUByte(); } -__READ_S(atInt16, Endian::Big) { var = r.readInt16Big(); } -__READ_S(atUint16, Endian::Big) { var = r.readUint16Big(); } -__READ_S(atInt32, Endian::Big) { var = r.readInt32Big(); } -__READ_S(atUint32, Endian::Big) { var = r.readUint32Big(); } -__READ_S(atInt64, Endian::Big) { var = r.readInt64Big(); } -__READ_S(atUint64, Endian::Big) { var = r.readUint64Big(); } -__READ_S(float, Endian::Big) { var = r.readFloatBig(); } -__READ_S(double, Endian::Big) { var = r.readDoubleBig(); } -__READ_S(atVec2f, Endian::Big) { var = r.readVec2fBig(); } -__READ_S(atVec2d, Endian::Big) { var = r.readVec2dBig(); } -__READ_S(atVec3f, Endian::Big) { var = r.readVec3fBig(); } -__READ_S(atVec3d, Endian::Big) { var = r.readVec3dBig(); } -__READ_S(atVec4f, Endian::Big) { var = r.readVec4fBig(); } -__READ_S(atVec4d, Endian::Big) { var = r.readVec4dBig(); } -__READ_WSTR_S(Endian::Big) { str = r.readWStringBig(); } -__READ_WSTRC_S(Endian::Big) { str = r.readWStringBig(count); } -__READ_S(bool, Endian::Little) { var = r.readBool(); } -__READ_S(atInt8, Endian::Little) { var = r.readByte(); } -__READ_S(atUint8, Endian::Little) { var = r.readUByte(); } -__READ_S(atInt16, Endian::Little) { var = r.readInt16Little(); } -__READ_S(atUint16, Endian::Little) { var = r.readUint16Little(); } -__READ_S(atInt32, Endian::Little) { var = r.readInt32Little(); } -__READ_S(atUint32, Endian::Little) { var = r.readUint32Little(); } -__READ_S(atInt64, Endian::Little) { var = r.readInt64Little(); } -__READ_S(atUint64, Endian::Little) { var = r.readUint64Little(); } -__READ_S(float, Endian::Little) { var = r.readFloatLittle(); } -__READ_S(double, Endian::Little) { var = r.readDoubleLittle(); } -__READ_S(atVec2f, Endian::Little) { var = r.readVec2fLittle(); } -__READ_S(atVec2d, Endian::Little) { var = r.readVec2dLittle(); } -__READ_S(atVec3f, Endian::Little) { var = r.readVec3fLittle(); } -__READ_S(atVec3d, Endian::Little) { var = r.readVec3dLittle(); } -__READ_S(atVec4f, Endian::Little) { var = r.readVec4fLittle(); } -__READ_S(atVec4d, Endian::Little) { var = r.readVec4dLittle(); } -__READ_WSTR_S(Endian::Little) { str = r.readWStringLittle(); } -__READ_WSTRC_S(Endian::Little) { str = r.readWStringLittle(count); } - -template -struct Write { - using PropT = std::conditional_t; - using StreamT = IStreamWriter; - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& w) { - if (PropOp != PropType::None) { - /* Accessed via Enumerate, header */ - if (PropOp == PropType::CRC64) - __Write64(w, id.crc64); - else - __Write32(w, id.rcrc32); - size_t binarySize = 0; - BinarySize::Do(id, var, binarySize); - DNAE == Endian::Big ? w.writeUint16Big(atUint16(binarySize)) : w.writeUint16Little(atUint16(binarySize)); - } - using PODType = std::underlying_type_t; - Write::Do(id, *reinterpret_cast(&var), w); - } - template - static std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& w) { - using CastT = __CastPODType; - if (PropOp != PropType::None) { - /* Accessed via Enumerate, header */ - if (PropOp == PropType::CRC64) - __Write64(w, id.crc64); - else - __Write32(w, id.rcrc32); - size_t binarySize = 0; - BinarySize::Do(id, static_cast(const_cast&>(var)), - binarySize); - __Write16(w, atUint16(binarySize)); - } - Write::Do(id, static_cast(const_cast&>(var)), w); - } - template - static std::enable_if_t<__IsDNARecord() && PropOp != PropType::None> Do(const PropId& id, T& var, StreamT& w) { - /* Accessed via Enumerate, header */ - if (PropOp == PropType::CRC64) - __Write64(w, id.crc64); - else - __Write32(w, id.rcrc32); - size_t binarySize = 0; - var.template Enumerate>(binarySize); - __Write16(w, atUint16(binarySize)); - - size_t propCount = 0; - var.template Enumerate>(propCount); - __Write16(w, atUint16(propCount)); - var.template Enumerate>(w); - } - template - static std::enable_if_t<__IsDNARecord() && PropOp == PropType::None> Do(const PropId& id, T& var, StreamT& w) { - var.template Enumerate>(w); - } - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& s) { - for (auto& v : var) { - Write::template Do, DNAE>(id, v, s); - } - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) { - Write::template Do(id, var, s); - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& w) { - for (T& v : vector) { - Write::template Do(id, v, w); - } - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& w) { - /* libc++ specializes vector as a bitstream */ - for (const T v : vector) - w.writeBool(v); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& w) { - if (buf) - w.writeUBytes(buf.get(), count); - } - template - static std::enable_if_t> Do(const PropId& id, std::string& str, StreamT& w) { - w.writeString(str); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) { w.writeString(str, count); } - template - static std::enable_if_t> Do(const PropId& id, std::wstring& str, StreamT& w) { - Write::Do(id, str, w); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) { - Write::Do(id, str, count, w); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) { w.seek(amount, whence); } - static void DoAlign(atInt64 amount, StreamT& w) { w.writeZeroTo((w.position() + amount - 1) / amount * amount); } -}; -#define __WRITE_S(type, endian) \ - template <> \ - template <> \ - inline void Write::Do(const PropId& id, type& var, Write::StreamT& w) -#define __WRITE_WSTR_S(endian) \ - template <> \ - template <> \ - inline void Write::Do(const PropId& id, std::wstring& str, Write::StreamT& w) -#define __WRITE_WSTRC_S(endian) \ - template <> \ - template <> \ - inline void Write::Do(const PropId& id, std::wstring& str, atInt32 count, Write::StreamT& w) -__WRITE_S(bool, Endian::Big) { w.writeBool(var); } -__WRITE_S(atInt8, Endian::Big) { w.writeByte(var); } -__WRITE_S(atUint8, Endian::Big) { w.writeUByte(var); } -__WRITE_S(atInt16, Endian::Big) { w.writeInt16Big(var); } -__WRITE_S(atUint16, Endian::Big) { w.writeUint16Big(var); } -__WRITE_S(atInt32, Endian::Big) { w.writeInt32Big(var); } -__WRITE_S(atUint32, Endian::Big) { w.writeUint32Big(var); } -__WRITE_S(atInt64, Endian::Big) { w.writeInt64Big(var); } -__WRITE_S(atUint64, Endian::Big) { w.writeUint64Big(var); } -__WRITE_S(float, Endian::Big) { w.writeFloatBig(var); } -__WRITE_S(double, Endian::Big) { w.writeDoubleBig(var); } -__WRITE_S(atVec2f, Endian::Big) { w.writeVec2fBig(var); } -__WRITE_S(atVec2d, Endian::Big) { w.writeVec2dBig(var); } -__WRITE_S(atVec3f, Endian::Big) { w.writeVec3fBig(var); } -__WRITE_S(atVec3d, Endian::Big) { w.writeVec3dBig(var); } -__WRITE_S(atVec4f, Endian::Big) { w.writeVec4fBig(var); } -__WRITE_S(atVec4d, Endian::Big) { w.writeVec4dBig(var); } -__WRITE_WSTR_S(Endian::Big) { w.writeWStringBig(str); } -__WRITE_WSTRC_S(Endian::Big) { w.writeWStringBig(str, count); } -__WRITE_S(bool, Endian::Little) { w.writeBool(var); } -__WRITE_S(atInt8, Endian::Little) { w.writeByte(var); } -__WRITE_S(atUint8, Endian::Little) { w.writeUByte(var); } -__WRITE_S(atInt16, Endian::Little) { w.writeInt16Little(var); } -__WRITE_S(atUint16, Endian::Little) { w.writeUint16Little(var); } -__WRITE_S(atInt32, Endian::Little) { w.writeInt32Little(var); } -__WRITE_S(atUint32, Endian::Little) { w.writeUint32Little(var); } -__WRITE_S(atInt64, Endian::Little) { w.writeInt64Little(var); } -__WRITE_S(atUint64, Endian::Little) { w.writeUint64Little(var); } -__WRITE_S(float, Endian::Little) { w.writeFloatLittle(var); } -__WRITE_S(double, Endian::Little) { w.writeDoubleLittle(var); } -__WRITE_S(atVec2f, Endian::Little) { w.writeVec2fLittle(var); } -__WRITE_S(atVec2d, Endian::Little) { w.writeVec2dLittle(var); } -__WRITE_S(atVec3f, Endian::Little) { w.writeVec3fLittle(var); } -__WRITE_S(atVec3d, Endian::Little) { w.writeVec3dLittle(var); } -__WRITE_S(atVec4f, Endian::Little) { w.writeVec4fLittle(var); } -__WRITE_S(atVec4d, Endian::Little) { w.writeVec4dLittle(var); } -__WRITE_WSTR_S(Endian::Little) { w.writeWStringLittle(str); } -__WRITE_WSTRC_S(Endian::Little) { w.writeWStringLittle(str, count); } - -template -struct ReadYaml { - using PropT = std::conditional_t; - using StreamT = YAMLDocReader; - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& r) { - using PODType = std::underlying_type_t; - ReadYaml::Do(id, *reinterpret_cast(&var), r); - } - template - static std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& r) { - using CastT = __CastPODType; - ReadYaml::Do(id, static_cast(var), r); - } - template - static std::enable_if_t<__IsDNARecord_v> Do(const PropId& id, T& var, StreamT& r) { - if (auto rec = r.enterSubRecord(id.name)) - var.template Enumerate>(r); - } - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& r) { - size_t _count; - if (auto __v = r.enterSubVector(id.name, _count)) { - for (size_t i = 0; i < _count && i < std::extent_v; ++i) { - ReadYaml::template Do, DNAE>({}, var[i], r); - } - } - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) { - /* Squelch size field access */ - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& r) { - size_t _count; - vector.clear(); - if (auto __v = r.enterSubVector(id.name, _count)) { - vector.reserve(_count); - for (size_t i = 0; i < _count; ++i) { - vector.emplace_back(); - ReadYaml::template Do({}, vector.back(), r); - } - } - /* Horrible reference abuse (but it works) */ - const_cast(count) = vector.size(); - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& r) { - /* libc++ specializes vector as a bitstream */ - size_t _count; - vector.clear(); - if (auto __v = r.enterSubVector(id.name, _count)) { - vector.reserve(_count); - for (size_t i = 0; i < _count; ++i) - vector.push_back(r.readBool()); - } - /* Horrible reference abuse (but it works) */ - const_cast(count) = vector.size(); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& r) { - buf = r.readUBytes(id.name); - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { - str = r.readString(id.name); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) { str = r.readString(id.name); } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& r) { - str = r.readWString(id.name); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) { - str = r.readWString(id.name); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) {} - static void DoAlign(atInt64 amount, StreamT& r) {} -}; -#define __READ_YAML_S(type, endian) \ - template <> \ - template <> \ - inline void ReadYaml::Do(const PropId& id, type& var, ReadYaml::StreamT& r) -__READ_YAML_S(bool, Endian::Big) { var = r.readBool(id.name); } -__READ_YAML_S(atInt8, Endian::Big) { var = r.readByte(id.name); } -__READ_YAML_S(atUint8, Endian::Big) { var = r.readUByte(id.name); } -__READ_YAML_S(atInt16, Endian::Big) { var = r.readInt16(id.name); } -__READ_YAML_S(atUint16, Endian::Big) { var = r.readUint16(id.name); } -__READ_YAML_S(atInt32, Endian::Big) { var = r.readInt32(id.name); } -__READ_YAML_S(atUint32, Endian::Big) { var = r.readUint32(id.name); } -__READ_YAML_S(atInt64, Endian::Big) { var = r.readInt64(id.name); } -__READ_YAML_S(atUint64, Endian::Big) { var = r.readUint64(id.name); } -__READ_YAML_S(float, Endian::Big) { var = r.readFloat(id.name); } -__READ_YAML_S(double, Endian::Big) { var = r.readDouble(id.name); } -__READ_YAML_S(atVec2f, Endian::Big) { var = r.readVec2f(id.name); } -__READ_YAML_S(atVec2d, Endian::Big) { var = r.readVec2d(id.name); } -__READ_YAML_S(atVec3f, Endian::Big) { var = r.readVec3f(id.name); } -__READ_YAML_S(atVec3d, Endian::Big) { var = r.readVec3d(id.name); } -__READ_YAML_S(atVec4f, Endian::Big) { var = r.readVec4f(id.name); } -__READ_YAML_S(atVec4d, Endian::Big) { var = r.readVec4d(id.name); } -__READ_YAML_S(bool, Endian::Little) { var = r.readBool(id.name); } -__READ_YAML_S(atInt8, Endian::Little) { var = r.readByte(id.name); } -__READ_YAML_S(atUint8, Endian::Little) { var = r.readUByte(id.name); } -__READ_YAML_S(atInt16, Endian::Little) { var = r.readInt16(id.name); } -__READ_YAML_S(atUint16, Endian::Little) { var = r.readUint16(id.name); } -__READ_YAML_S(atInt32, Endian::Little) { var = r.readInt32(id.name); } -__READ_YAML_S(atUint32, Endian::Little) { var = r.readUint32(id.name); } -__READ_YAML_S(atInt64, Endian::Little) { var = r.readInt64(id.name); } -__READ_YAML_S(atUint64, Endian::Little) { var = r.readUint64(id.name); } -__READ_YAML_S(float, Endian::Little) { var = r.readFloat(id.name); } -__READ_YAML_S(double, Endian::Little) { var = r.readDouble(id.name); } -__READ_YAML_S(atVec2f, Endian::Little) { var = r.readVec2f(id.name); } -__READ_YAML_S(atVec2d, Endian::Little) { var = r.readVec2d(id.name); } -__READ_YAML_S(atVec3f, Endian::Little) { var = r.readVec3f(id.name); } -__READ_YAML_S(atVec3d, Endian::Little) { var = r.readVec3d(id.name); } -__READ_YAML_S(atVec4f, Endian::Little) { var = r.readVec4f(id.name); } -__READ_YAML_S(atVec4d, Endian::Little) { var = r.readVec4d(id.name); } - -template -struct WriteYaml { - using PropT = std::conditional_t; - using StreamT = YAMLDocWriter; - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& w) { - using PODType = std::underlying_type_t; - WriteYaml::Do(id, *reinterpret_cast(&var), w); - } - template - static std::enable_if_t<__IsPODType_v> Do(const PropId& id, T& var, StreamT& w) { - using CastT = __CastPODType; - WriteYaml::Do(id, static_cast(const_cast&>(var)), w); - } - template - static std::enable_if_t<__IsDNARecord_v> Do(const PropId& id, T& var, StreamT& w) { - if (auto rec = w.enterSubRecord(id.name)) - var.template Enumerate>(w); - } - template - static std::enable_if_t> Do(const PropId& id, T& var, StreamT& w) { - if (auto __v = w.enterSubVector(id.name)) { - for (auto& v : var) { - WriteYaml::template Do, DNAE>({}, v, w); - } - } - } - template - static void DoSize(const PropId& id, T& var, StreamT& s) { - /* Squelch size field access */ - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& w) { - if (auto __v = w.enterSubVector(id.name)) { - for (T& v : vector) { - WriteYaml::template Do(id, v, w); - } - } - } - template - static std::enable_if_t> Do(const PropId& id, std::vector& vector, const S& count, - StreamT& w) { - /* libc++ specializes vector as a bitstream */ - if (auto __v = w.enterSubVector(id.name)) - for (const T v : vector) - w.writeBool(v); - } - static void Do(const PropId& id, std::unique_ptr& buf, size_t count, StreamT& w) { - w.writeUBytes(id.name, buf, count); - } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& w) { - w.writeString(id.name, str); - } - static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) { w.writeString(id.name, str); } - template - static std::enable_if_t> Do(const PropId& id, T& str, StreamT& w) { - w.writeWString(id.name, str); - } - template - static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) { - w.writeWString(id.name, str); - } - static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) {} - static void DoAlign(atInt64 amount, StreamT& w) {} -}; -#define __WRITE_YAML_S(type, endian) \ - template <> \ - template <> \ - inline void WriteYaml::Do(const PropId& id, type& var, WriteYaml::StreamT& w) -__WRITE_YAML_S(bool, Endian::Big) { w.writeBool(id.name, var); } -__WRITE_YAML_S(atInt8, Endian::Big) { w.writeByte(id.name, var); } -__WRITE_YAML_S(atUint8, Endian::Big) { w.writeUByte(id.name, var); } -__WRITE_YAML_S(atInt16, Endian::Big) { w.writeInt16(id.name, var); } -__WRITE_YAML_S(atUint16, Endian::Big) { w.writeUint16(id.name, var); } -__WRITE_YAML_S(atInt32, Endian::Big) { w.writeInt32(id.name, var); } -__WRITE_YAML_S(atUint32, Endian::Big) { w.writeUint32(id.name, var); } -__WRITE_YAML_S(atInt64, Endian::Big) { w.writeInt64(id.name, var); } -__WRITE_YAML_S(atUint64, Endian::Big) { w.writeUint64(id.name, var); } -__WRITE_YAML_S(float, Endian::Big) { w.writeFloat(id.name, var); } -__WRITE_YAML_S(double, Endian::Big) { w.writeDouble(id.name, var); } -__WRITE_YAML_S(atVec2f, Endian::Big) { w.writeVec2f(id.name, var); } -__WRITE_YAML_S(atVec2d, Endian::Big) { w.writeVec2d(id.name, var); } -__WRITE_YAML_S(atVec3f, Endian::Big) { w.writeVec3f(id.name, var); } -__WRITE_YAML_S(atVec3d, Endian::Big) { w.writeVec3d(id.name, var); } -__WRITE_YAML_S(atVec4f, Endian::Big) { w.writeVec4f(id.name, var); } -__WRITE_YAML_S(atVec4d, Endian::Big) { w.writeVec4d(id.name, var); } -__WRITE_YAML_S(bool, Endian::Little) { w.writeBool(id.name, var); } -__WRITE_YAML_S(atInt8, Endian::Little) { w.writeByte(id.name, var); } -__WRITE_YAML_S(atUint8, Endian::Little) { w.writeUByte(id.name, var); } -__WRITE_YAML_S(atInt16, Endian::Little) { w.writeInt16(id.name, var); } -__WRITE_YAML_S(atUint16, Endian::Little) { w.writeUint16(id.name, var); } -__WRITE_YAML_S(atInt32, Endian::Little) { w.writeInt32(id.name, var); } -__WRITE_YAML_S(atUint32, Endian::Little) { w.writeUint32(id.name, var); } -__WRITE_YAML_S(atInt64, Endian::Little) { w.writeInt64(id.name, var); } -__WRITE_YAML_S(atUint64, Endian::Little) { w.writeUint64(id.name, var); } -__WRITE_YAML_S(float, Endian::Little) { w.writeFloat(id.name, var); } -__WRITE_YAML_S(double, Endian::Little) { w.writeDouble(id.name, var); } -__WRITE_YAML_S(atVec2f, Endian::Little) { w.writeVec2f(id.name, var); } -__WRITE_YAML_S(atVec2d, Endian::Little) { w.writeVec2d(id.name, var); } -__WRITE_YAML_S(atVec3f, Endian::Little) { w.writeVec3f(id.name, var); } -__WRITE_YAML_S(atVec3d, Endian::Little) { w.writeVec3d(id.name, var); } -__WRITE_YAML_S(atVec4f, Endian::Little) { w.writeVec4f(id.name, var); } -__WRITE_YAML_S(atVec4d, Endian::Little) { w.writeVec4d(id.name, var); } - -template -void __Do(const PropId& id, T& var, typename Op::StreamT& s) { - Op::template Do(id, var, s); -} - -template -void __DoSize(const PropId& id, T& var, typename Op::StreamT& s) { - Op::template DoSize(id, var, s); -} - -template -void __Do(const PropId& id, std::vector& vector, const S& count, typename Op::StreamT& s) { - Op::template Do(id, vector, count, s); -} - -template -void __Do(const PropId& id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) { - Op::Do(id, buf, count, s); -} - -template -void __Do(const PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) { - Op::Do(id, str, count, s); -} - -template -void __Do(const PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { - Op::template Do(id, str, count, s); -} - -template -void __DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { - Op::DoSeek(delta, whence, s); -} - -template -void __DoAlign(atInt64 amount, typename Op::StreamT& s) { - Op::DoAlign(amount, s); -} - -template -void __Read(T& obj, athena::io::IStreamReader& r) { - __Do, T, T::DNAEndian>({}, obj, r); -} - -template -void __Write(const T& obj, athena::io::IStreamWriter& w) { - __Do, T, T::DNAEndian>({}, const_cast(obj), w); -} - -template -void __BinarySize(const T& obj, size_t& s) { - __Do, T, T::DNAEndian>({}, const_cast(obj), s); -} - -template -void __PropCount(const T& obj, size_t& s) { - const_cast(obj).template Enumerate>(s); -} - -template -void __ReadYaml(T& obj, athena::io::YAMLDocReader& r) { - obj.template Enumerate>(r); -} - -template -void __WriteYaml(const T& obj, athena::io::YAMLDocWriter& w) { - const_cast(obj).template Enumerate>(w); -} - -template -void __ReadProp(T& obj, athena::io::IStreamReader& r) { - /* Read root 0xffffffff hash (hashed empty string) */ - T::DNAEndian == Endian::Big ? r.readUint32Big() : r.readUint32Little(); - atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little(); - atInt64 start = r.position(); - __Do, T, T::DNAEndian>({}, obj, r); - atInt64 actualRead = r.position() - start; - if (actualRead != size) - r.seek(size - actualRead); -} - -template -void __WriteProp(const T& obj, athena::io::IStreamWriter& w) { - __Do, T, T::DNAEndian>({}, const_cast(obj), w); -} - -template -void __BinarySizeProp(const T& obj, size_t& s) { - __Do, T, T::DNAEndian>({}, const_cast(obj), s); -} - -template -void __ReadProp64(T& obj, athena::io::IStreamReader& r) { - /* Read root 0x0 hash (hashed empty string) */ - T::DNAEndian == Endian::Big ? r.readUint64Big() : r.readUint64Little(); - atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little(); - atInt64 start = r.position(); - __Do, T, T::DNAEndian>({}, obj, r); - atInt64 actualRead = r.position() - start; - if (actualRead != size) - r.seek(size - actualRead); -} - -template -void __WriteProp64(const T& obj, athena::io::IStreamWriter& w) { - __Do, T, T::DNAEndian>({}, const_cast(obj), w); -} - -template -void __BinarySizeProp64(const T& obj, size_t& s) { - __Do, T, T::DNAEndian>({}, const_cast(obj), s); -} - -} // namespace athena::io - -#define AT_DECL_DNA_DO \ - template \ - void Do(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \ - athena::io::__Do(_id, var, s); \ - } \ - template \ - void DoSize(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \ - athena::io::__DoSize(_id, var, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::vector& var, const S& count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, var, count, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, buf, count, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::string& str, atInt32 count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, str, count, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, str, count, s); \ - } \ - template \ - void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { \ - athena::io::__DoSeek(delta, whence, s); \ - } \ - template \ - void DoAlign(atInt64 amount, typename Op::StreamT& s) { \ - athena::io::__DoAlign(amount, s); \ - } \ - template \ - void Enumerate(typename Op::StreamT& s); \ - static std::string_view DNAType(); - -#define AT_DECL_DNA \ - AT_DECL_DNA_DO \ - void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \ - void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \ - void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } - -#define AT_DECL_DNA_YAML \ - AT_DECL_DNA \ - void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \ - void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } - -#define AT_DECL_EXPLICIT_DNA \ - AT_DECL_DNA \ - Delete __d; - -#define AT_DECL_EXPLICIT_DNAV \ - AT_DECL_DNAV \ - Delete __d; - -#define AT_DECL_EXPLICIT_DNAV_NO_TYPE \ - AT_DECL_DNAV_NO_TYPE \ - Delete __d; - -#define AT_DECL_EXPLICIT_DNA_YAML \ - AT_DECL_DNA_YAML \ - Delete __d; - -#define AT_DECL_EXPLICIT_DNA_YAMLV \ - AT_DECL_DNA_YAMLV \ - Delete __d; - -#define AT_DECL_EXPLICIT_DNA_YAMLV_NO_TYPE \ - AT_DECL_DNA_YAMLV_NO_TYPE \ - Delete __d; -#define AT_DECL_DNAV \ - AT_DECL_DNA_DO \ - void read(athena::io::IStreamReader& r) override { athena::io::__Read(*this, r); } \ - void write(athena::io::IStreamWriter& w) const override { athena::io::__Write(*this, w); } \ - void binarySize(size_t& s) const override { athena::io::__BinarySize(*this, s); } \ - std::string_view DNATypeV() const override { return DNAType(); } - -#define AT_DECL_DNAV_NO_TYPE \ - AT_DECL_DNA_DO \ - void read(athena::io::IStreamReader& r) override { athena::io::__Read(*this, r); } \ - void write(athena::io::IStreamWriter& w) const override { athena::io::__Write(*this, w); } \ - void binarySize(size_t& s) const override { athena::io::__BinarySize(*this, s); } - -#define AT_DECL_DNA_YAMLV \ - AT_DECL_DNAV \ - void read(athena::io::YAMLDocReader& r) override { athena::io::__ReadYaml(*this, r); } \ - void write(athena::io::YAMLDocWriter& w) const override { athena::io::__WriteYaml(*this, w); } - -#define AT_DECL_DNA_YAMLV_NO_TYPE \ - AT_DECL_DNAV_NO_TYPE \ - void read(athena::io::YAMLDocReader& r) override { athena::io::__ReadYaml(*this, r); } \ - void write(athena::io::YAMLDocWriter& w) const override { athena::io::__WriteYaml(*this, w); } - -#define AT_SPECIALIZE_DNA(...) \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Read::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Write::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::BinarySize::StreamT & s); - -#define AT_SPECIALIZE_DNA_YAML(...) \ - AT_SPECIALIZE_DNA(__VA_ARGS__) \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::ReadYaml::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::WriteYaml::StreamT & s); - -#define AT_DECL_PROPDNA \ - template \ - void Do(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \ - athena::io::__Do(_id, var, s); \ - } \ - template \ - void DoSize(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \ - athena::io::__DoSize(_id, var, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::vector& var, const S& count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, var, count, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::unique_ptr& buf, size_t count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, buf, count, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::string& str, atInt32 count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, str, count, s); \ - } \ - template \ - void Do(const athena::io::PropId& _id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { \ - athena::io::__Do(_id, str, count, s); \ - } \ - template \ - void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { \ - athena::io::__DoSeek(delta, whence, s); \ - } \ - template \ - void DoAlign(atInt64 amount, typename Op::StreamT& s) { \ - athena::io::__DoAlign(amount, s); \ - } \ - template \ - void Enumerate(typename Op::StreamT& s); \ - template \ - bool Lookup(uint64_t hash, typename Op::StreamT& s); \ - static std::string_view DNAType(); \ - void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \ - void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \ - void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } \ - void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \ - void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } \ - void readProp(athena::io::IStreamReader& r) { athena::io::__ReadProp(*this, r); } \ - void writeProp(athena::io::IStreamWriter& w) const { athena::io::__WriteProp(*this, w); } \ - void binarySizeProp(size_t& s) const { athena::io::__BinarySizeProp(*this, s); } \ - void propCount(size_t& s) const { athena::io::__PropCount(*this, s); } \ - void readProp64(athena::io::IStreamReader& r) { athena::io::__ReadProp64(*this, r); } \ - void writeProp64(athena::io::IStreamWriter& w) const { athena::io::__WriteProp64(*this, w); } \ - void binarySizeProp64(size_t& s) const { athena::io::__BinarySizeProp64(*this, s); } - -#define AT_DECL_EXPLICIT_PROPDNA \ - AT_DECL_PROPDNA \ - Delete __d; - -#define AT_SPECIALIZE_PROPDNA(...) \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Read::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Write::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::BinarySize::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::ReadYaml::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::WriteYaml::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::Read::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Read::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::Write::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Write::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::BinarySize::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::BinarySize::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::PropCount::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::PropCount::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::ReadYaml::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::ReadYaml::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::WriteYaml::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::WriteYaml::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::Read::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Read::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::Write::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::Write::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::BinarySize::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::BinarySize::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::PropCount::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::PropCount::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::ReadYaml::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::ReadYaml::StreamT & s); \ - template bool __VA_ARGS__::Lookup>( \ - uint64_t hash, athena::io::WriteYaml::StreamT & s); \ - template void __VA_ARGS__::Enumerate>( \ - athena::io::WriteYaml::StreamT & s); - -#define AT_SUBDECL_DNA \ - void _read(athena::io::IStreamReader& r); \ - void _write(athena::io::IStreamWriter& w) const; \ - void _binarySize(size_t& s) const; \ - void _read(athena::io::YAMLDocReader& r); \ - void _write(athena::io::YAMLDocWriter& w) const; - -#define AT_SUBDECL_DNA_YAML \ - AT_SUBDECL_DNA \ - void _read(athena::io::YAMLDocReader& r); \ - void _write(athena::io::YAMLDocWriter& w) const; - -#define AT_SUBSPECIALIZE_DNA(...) \ - template <> \ - template <> \ - void __VA_ARGS__::Enumerate::BinarySize>(typename BinarySize::StreamT & s) { \ - _binarySize(s); \ - } \ - template <> \ - template <> \ - void __VA_ARGS__::Enumerate::Read>(typename Read::StreamT & r) { \ - _read(r); \ - } \ - template <> \ - template <> \ - void __VA_ARGS__::Enumerate::Write>(typename Write::StreamT & w) { \ - _write(w); \ - } - -#define AT_SUBSPECIALIZE_DNA_YAML(...) \ - template <> \ - template <> \ - void __VA_ARGS__::Enumerate::ReadYaml>(typename ReadYaml::StreamT & r) { \ - _read(r); \ - } \ - template <> \ - template <> \ - void __VA_ARGS__::Enumerate::WriteYaml>(typename WriteYaml::StreamT & w) { \ - _write(w); \ - } \ - AT_SUBSPECIALIZE_DNA(__VA_ARGS__) diff --git a/include/athena/DNAYaml.hpp b/include/athena/DNAYaml.hpp deleted file mode 100644 index e7ba501..0000000 --- a/include/athena/DNAYaml.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once - -#include - -#include "athena/DNA.hpp" -#include "athena/FileReader.hpp" -#include "athena/FileWriter.hpp" -#include "athena/YAMLDocReader.hpp" -#include "athena/YAMLDocWriter.hpp" - -namespace athena::io { - -template -std::string_view __GetDNAName(const T& dna) { - if constexpr (__IsDNAVRecord_v) { - return dna.DNATypeV(); - } else { - return dna.DNAType(); - } -} - -template -std::string ToYAMLString(const T& dna) { - YAMLDocWriter docWriter(__GetDNAName(dna)); - - std::string res; - yaml_emitter_set_output(docWriter.getEmitter(), (yaml_write_handler_t*)YAMLStdStringWriter, &res); - yaml_emitter_set_unicode(docWriter.getEmitter(), true); - yaml_emitter_set_width(docWriter.getEmitter(), -1); - - dna.write(docWriter); - if (!docWriter.finish(nullptr)) - return std::string(); - - return res; -} - -template -bool FromYAMLString(T& dna, std::string_view str) { - YAMLStdStringViewReaderState reader(str); - YAMLDocReader docReader; - yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); - if (!docReader.parse(nullptr)) - return false; - dna.read(docReader); - return true; -} - -template -bool ValidateFromYAMLString(std::string_view str) { - YAMLStdStringViewReaderState reader(str); - YAMLDocReader docReader; - yaml_parser_set_input(docReader.getParser(), (yaml_read_handler_t*)YAMLStdStringReader, &reader); - bool retval = docReader.ValidateClassType(DNASubtype::DNAType()); - return retval; -} - -template -bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout) { - YAMLDocWriter docWriter(__GetDNAName(dna)); - - yaml_emitter_set_unicode(docWriter.getEmitter(), true); - yaml_emitter_set_width(docWriter.getEmitter(), -1); - - dna.write(docWriter); - return docWriter.finish(&fout); -} - -template -bool ToYAMLStream(const T& dna, athena::io::IStreamWriter& fout, void (T::*fn)(YAMLDocWriter& out) const) { - YAMLDocWriter docWriter(__GetDNAName(dna)); - - yaml_emitter_set_unicode(docWriter.getEmitter(), true); - yaml_emitter_set_width(docWriter.getEmitter(), -1); - - (dna.*fn)(docWriter); - return docWriter.finish(&fout); -} - -template -bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin) { - YAMLDocReader docReader; - if (!docReader.parse(&fin)) - return false; - dna.read(docReader); - return true; -} - -template -bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin, void (T::*fn)(YAMLDocReader& in)) { - YAMLDocReader docReader; - if (!docReader.parse(&fin)) - return false; - (dna.*fn)(docReader); - return true; -} - -template -bool MergeToYAMLFile(const T& dna, const NameT& filename) { - athena::io::FileReader r(filename); - YAMLDocWriter docWriter(__GetDNAName(dna), r.isOpen() ? &r : nullptr); - r.close(); - - dna.write(docWriter); - athena::io::FileWriter w(filename); - if (!w.isOpen()) - return false; - return docWriter.finish(&w); -} - -template -bool ValidateFromYAMLStream(athena::io::IStreamReader& fin) { - YAMLDocReader reader; - atUint64 pos = fin.position(); - yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)YAMLAthenaReader, &fin); - bool retval = reader.ValidateClassType(DNASubtype::DNAType()); - fin.seek(pos, athena::SeekOrigin::Begin); - return retval; -} - -} // namespace athena::io diff --git a/include/athena/Global.hpp b/include/athena/Global.hpp index 3fa5a27..04e2794 100644 --- a/include/athena/Global.hpp +++ b/include/athena/Global.hpp @@ -3,7 +3,7 @@ #include #include "athena/Types.hpp" -#include +#include #ifdef _MSC_VER #pragma warning(disable : 4996) @@ -17,11 +17,11 @@ #include #if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) -#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) -#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #if !defined(S_ISLNK) @@ -118,27 +118,10 @@ enum class SeekOrigin { Begin, Current, End }; enum class Endian { Little, Big }; -namespace io { -template -struct DNA; -template -struct DNAV; - -template -using __IsDNARecord = std::disjunction, T>, std::is_base_of, T>>; -template -constexpr bool __IsDNARecord_v = __IsDNARecord::value; - -template -using __IsDNAVRecord = - std::disjunction, T>, std::is_base_of, T>>; -template -constexpr bool __IsDNAVRecord_v = __IsDNAVRecord::value; -} // namespace io } // namespace athena typedef void (*atEXCEPTION_HANDLER)(athena::error::Level level, const char* /*file*/, const char*, int /*line*/, - fmt::string_view fmt, fmt::format_args args); + std::string_view fmt, std::format_args args); atEXCEPTION_HANDLER atGetExceptionHandler(); /** @@ -150,54 +133,47 @@ void atSetExceptionHandler(atEXCEPTION_HANDLER func); std::ostream& operator<<(std::ostream& os, const athena::SeekOrigin& origin); std::ostream& operator<<(std::ostream& os, const athena::Endian& endian); -template -constexpr auto __FIRST_ARG__(First first, Rest...) { return first; } -template -auto __make_args_checked__(const S& format_str, Args&&... args) { - return fmt::make_args_checked(format_str, std::forward(args)...); -} - #ifndef NDEBUG -#define atDebug(...) \ +#define atDebug(fmt, ...) \ do { \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \ - __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \ - __make_args_checked__(__VA_ARGS__)); \ + __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, \ + std::make_format_args(__VA_ARGS__)); \ } while (0) #else #define atDebug(...) #endif -#define atMessage(...) \ +#define atMessage(fmt, ...) \ do { \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \ - __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \ - __make_args_checked__(__VA_ARGS__)); \ + __handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, \ + std::make_format_args(__VA_ARGS__)); \ } while (0) -#define atWarning(...) \ +#define atWarning(fmt, ...) \ do { \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) { \ - __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \ - __make_args_checked__(__VA_ARGS__)); \ + __handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, \ + std::make_format_args(__VA_ARGS__)); \ } \ } while (0) -#define atError(...) \ +#define atError(fmt, ...) \ do { \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \ - __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \ - __make_args_checked__(__VA_ARGS__)); \ + __handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, \ + std::make_format_args(__VA_ARGS__)); \ } while (0) -#define atFatal(...) \ +#define atFatal(fmt, ...) \ do { \ atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ if (__handler) \ - __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \ - __make_args_checked__(__VA_ARGS__)); \ + __handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, \ + std::make_format_args(__VA_ARGS__)); \ } while (0) diff --git a/include/athena/IStreamWriter.hpp b/include/athena/IStreamWriter.hpp index 2c12984..253b345 100644 --- a/include/athena/IStreamWriter.hpp +++ b/include/athena/IStreamWriter.hpp @@ -661,7 +661,7 @@ public: utf8proc_int32_t wc; utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return; } buf += len; @@ -675,7 +675,7 @@ public: if (*buf) { utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return; } buf += len; @@ -709,7 +709,7 @@ public: utf8proc_int32_t wc; utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return; } buf += len; @@ -723,7 +723,7 @@ public: if (*buf) { utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return; } buf += len; @@ -758,7 +758,7 @@ public: utf8proc_int32_t wc; utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return; } buf += len; @@ -772,7 +772,7 @@ public: if (*buf) { utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return; } buf += len; diff --git a/include/athena/YAMLDocReader.hpp b/include/athena/YAMLDocReader.hpp index ed793cd..44cefbe 100644 --- a/include/athena/YAMLDocReader.hpp +++ b/include/athena/YAMLDocReader.hpp @@ -61,12 +61,6 @@ public: RecordRAII enterSubRecord(std::string_view name = {}); - template - void enumerate(std::string_view name, T& record, std::enable_if_t<__IsDNARecord_v>* = nullptr) { - if (auto rec = enterSubRecord(name)) - record.read(*this); - } - class VectorRAII { friend class YAMLDocReader; YAMLDocReader* m_r = nullptr; diff --git a/include/athena/YAMLDocWriter.hpp b/include/athena/YAMLDocWriter.hpp index bac44d9..9acec7a 100644 --- a/include/athena/YAMLDocWriter.hpp +++ b/include/athena/YAMLDocWriter.hpp @@ -47,12 +47,6 @@ public: RecordRAII enterSubRecord(std::string_view name = {}); - template - void enumerate(std::string_view name, T& record, std::enable_if_t<__IsDNARecord_v>* = nullptr) { - if (auto rec = enterSubRecord(name)) - record.write(*this); - } - class VectorRAII { friend class YAMLDocWriter; YAMLDocWriter* m_w = nullptr; diff --git a/src/athena/DNAYaml.cpp b/src/athena/DNAYaml.cpp deleted file mode 100644 index e8ac58f..0000000 --- a/src/athena/DNAYaml.cpp +++ /dev/null @@ -1,1105 +0,0 @@ -#include "athena/DNAYaml.hpp" - -#include -#include -#include - -#include "athena/YAMLCommon.hpp" - -namespace athena::io { -using namespace std::literals; - -template <> -bool NodeToVal(const YAMLNode* node) { - char firstCh = tolower(node->m_scalarString[0]); - if (firstCh == 't') - return true; - else if (firstCh == 'f') - return false; - else if (isdigit(firstCh) && firstCh != 0) - return true; - return false; -} - -std::unique_ptr ValToNode(bool val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = val ? "True" : "False"; - return ret; -} - -template <> -atInt8 NodeToVal(const YAMLNode* node) { - return strtol(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atInt8 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("{}"), int(val)); - return ret; -} - -template <> -atUint8 NodeToVal(const YAMLNode* node) { - return strtoul(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atUint8 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("0x{:02X}"), val); - return ret; -} - -template <> -atInt16 NodeToVal(const YAMLNode* node) { - return strtol(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atInt16 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("{}"), int(val)); - return ret; -} - -template <> -atUint16 NodeToVal(const YAMLNode* node) { - return strtoul(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atUint16 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("0x{:04X}"), val); - return ret; -} - -template <> -atInt32 NodeToVal(const YAMLNode* node) { - return strtol(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atInt32 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("{}"), int(val)); - return ret; -} - -template <> -atUint32 NodeToVal(const YAMLNode* node) { - return strtoul(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atUint32 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("0x{:08X}"), val); - return ret; -} - -template <> -atInt64 NodeToVal(const YAMLNode* node) { - return std::strtoll(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atInt64 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("{}"), val); - return ret; -} - -template <> -atUint64 NodeToVal(const YAMLNode* node) { - return std::strtoull(node->m_scalarString.c_str(), nullptr, 0); -} - -std::unique_ptr ValToNode(atUint64 val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("0x{:016X}"), val); - return ret; -} - -template <> -float NodeToVal(const YAMLNode* node) { - return strtof(node->m_scalarString.c_str(), nullptr); -} - -std::unique_ptr ValToNode(float val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("{}"), val); - return ret; -} - -template <> -double NodeToVal(const YAMLNode* node) { - return strtod(node->m_scalarString.c_str(), nullptr); -} - -std::unique_ptr ValToNode(double val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = fmt::format(FMT_STRING("{}"), val); - return ret; -} - -template -RETURNTYPE NodeToVec(const YAMLNode* node) { - constexpr bool isDouble = - std::is_same_v || std::is_same_v || std::is_same_v; - RETURNTYPE retval = {}; - auto it = node->m_seqChildren.begin(); - simd_values> f; - for (size_t i = 0; i < 4 && it != node->m_seqChildren.end(); ++i, ++it) { - YAMLNode* snode = it->get(); - if (snode->m_type == YAML_SCALAR_NODE) { - if constexpr (isDouble) { - f[i] = NodeToVal(snode); - } else { - f[i] = NodeToVal(snode); - } - } else { - f[i] = 0.0; - } - } - retval.simd.copy_from(f); - return retval; -} - -template <> -atVec2f NodeToVal(const YAMLNode* node) { - return NodeToVec(node); -} - -std::unique_ptr ValToNode(const atVec2f& val) { - auto ret = std::make_unique(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(2); - simd_floats f(val.simd); - for (size_t i = 0; i < 2; ++i) { - auto comp = std::make_unique(YAML_SCALAR_NODE); - comp->m_scalarString = fmt::format(FMT_STRING("{}"), f[i]); - ret->m_seqChildren.push_back(std::move(comp)); - } - return ret; -} - -template <> -atVec3f NodeToVal(const YAMLNode* node) { - return NodeToVec(node); -} - -std::unique_ptr ValToNode(const atVec3f& val) { - auto ret = std::make_unique(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(3); - simd_floats f(val.simd); - for (size_t i = 0; i < 3; ++i) { - auto comp = std::make_unique(YAML_SCALAR_NODE); - comp->m_scalarString = fmt::format(FMT_STRING("{}"), f[i]); - ret->m_seqChildren.push_back(std::move(comp)); - } - return ret; -} - -template <> -atVec4f NodeToVal(const YAMLNode* node) { - return NodeToVec(node); -} - -std::unique_ptr ValToNode(const atVec4f& val) { - auto ret = std::make_unique(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(4); - simd_floats f(val.simd); - for (size_t i = 0; i < 4; ++i) { - auto comp = std::make_unique(YAML_SCALAR_NODE); - comp->m_scalarString = fmt::format(FMT_STRING("{}"), f[i]); - ret->m_seqChildren.push_back(std::move(comp)); - } - return ret; -} - -template <> -atVec2d NodeToVal(const YAMLNode* node) { - return NodeToVec(node); -} - -std::unique_ptr ValToNode(const atVec2d& val) { - auto ret = std::make_unique(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(2); - simd_doubles f(val.simd); - for (size_t i = 0; i < 2; ++i) { - auto comp = std::make_unique(YAML_SCALAR_NODE); - comp->m_scalarString = fmt::format(FMT_STRING("{}"), f[i]); - ret->m_seqChildren.push_back(std::move(comp)); - } - return ret; -} - -template <> -atVec3d NodeToVal(const YAMLNode* node) { - return NodeToVec(node); -} - -std::unique_ptr ValToNode(const atVec3d& val) { - auto ret = std::make_unique(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(3); - simd_doubles f(val.simd); - for (size_t i = 0; i < 3; ++i) { - auto comp = std::make_unique(YAML_SCALAR_NODE); - comp->m_scalarString = fmt::format(FMT_STRING("{}"), f[i]); - ret->m_seqChildren.push_back(std::move(comp)); - } - return ret; -} - -template <> -atVec4d NodeToVal(const YAMLNode* node) { - return NodeToVec(node); -} - -std::unique_ptr ValToNode(const atVec4d& val) { - auto ret = std::make_unique(YAML_SEQUENCE_NODE); - ret->m_seqChildren.reserve(4); - simd_doubles f(val.simd); - for (size_t i = 0; i < 4; ++i) { - auto comp = std::make_unique(YAML_SCALAR_NODE); - comp->m_scalarString = fmt::format(FMT_STRING("{}"), f[i]); - ret->m_seqChildren.push_back(std::move(comp)); - } - return ret; -} - -template <> -std::unique_ptr NodeToVal(const YAMLNode* node) { - return base64_decode(node->m_scalarString); -} - -std::unique_ptr ValToNode(const std::unique_ptr& val, size_t byteCount) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - if (val) - ret->m_scalarString = base64_encode(val.get(), byteCount); - return ret; -} - -template <> -std::string NodeToVal(const YAMLNode* node) { - return node->m_scalarString; -} - -std::unique_ptr ValToNode(std::string_view val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString = val; - return ret; -} - -template <> -std::wstring NodeToVal(const YAMLNode* node) { - std::wstring retval; - retval.reserve(node->m_scalarString.length()); - const utf8proc_uint8_t* buf = reinterpret_cast(node->m_scalarString.c_str()); - while (*buf) { - utf8proc_int32_t wc; - utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); - if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); - return retval; - } - buf += len; - retval += wchar_t(wc); - } - return retval; -} - -std::unique_ptr ValToNode(std::wstring_view val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString.reserve(val.length()); - for (wchar_t ch : val) { - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); - if (c < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while encoding")); - return ret; - } - ret->m_scalarString.append(reinterpret_cast(mb), c); - } - return ret; -} - -std::unique_ptr ValToNode(std::u16string_view val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString.reserve(val.length()); - for (char16_t ch : val) { - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); - if (c < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while encoding")); - return ret; - } - ret->m_scalarString.append(reinterpret_cast(mb), c); - } - return ret; -} - -std::unique_ptr ValToNode(std::u32string_view val) { - auto ret = std::make_unique(YAML_SCALAR_NODE); - ret->m_scalarString.reserve(val.length()); - for (char32_t ch : val) { - utf8proc_uint8_t mb[4]; - utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); - if (c < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while encoding")); - return ret; - } - ret->m_scalarString.append(reinterpret_cast(mb), c); - } - return ret; -} - -static std::string_view ErrorString(yaml_error_type_t errt) { - switch (errt) { - case YAML_NO_ERROR: - return "No Error"sv; - case YAML_MEMORY_ERROR: - return "Memory Error"sv; - case YAML_READER_ERROR: - return "Reader Error"sv; - case YAML_SCANNER_ERROR: - return "Scanner Error"sv; - case YAML_PARSER_ERROR: - return "Parser Error"sv; - case YAML_COMPOSER_ERROR: - return "Composer Error"sv; - case YAML_WRITER_ERROR: - return "Writer Error"sv; - case YAML_EMITTER_ERROR: - return "Emitter Error"sv; - } - return "Unknown Error"sv; -} - -void HandleYAMLParserError(yaml_parser_t* parser) { - atError(FMT_STRING("YAML error: {}: {}"), ErrorString(parser->error), parser->problem ? parser->problem : ""); -} - -void HandleYAMLEmitterError(yaml_emitter_t* emitter) { - atError(FMT_STRING("YAML error: {}: {}"), ErrorString(emitter->error), emitter->problem ? emitter->problem : ""); -} - -int YAMLStdStringReader(YAMLStdStringViewReaderState* reader, unsigned char* buffer, size_t size, size_t* size_read) { - size_t diff = reader->end - reader->begin; - if (!diff) { - *size_read = 0; - } else if (diff < size) { - memcpy(buffer, &*reader->begin, diff); - *size_read = diff; - } else { - memcpy(buffer, &*reader->begin, size); - *size_read = size; - } - return 1; -} - -int YAMLStdStringWriter(std::string* str, unsigned char* buffer, size_t size) { - str->append((char*)buffer, size); - return 1; -} - -int YAMLAthenaReader(athena::io::IStreamReader* reader, unsigned char* buffer, size_t size, size_t* size_read) { - *size_read = reader->readUBytesToBuf(buffer, size); - return 1; -} - -int YAMLAthenaWriter(athena::io::IStreamWriter* writer, unsigned char* buffer, size_t size) { - writer->writeUBytes(buffer, size); - return 1; -} - -YAMLDocWriter::YAMLDocWriter(std::string_view classType, athena::io::IStreamReader* reader) { - if (!yaml_emitter_initialize(&m_emitter)) { - HandleYAMLEmitterError(&m_emitter); - return; - } - yaml_emitter_set_unicode(&m_emitter, true); - yaml_emitter_set_width(&m_emitter, -1); - - if (reader) { - YAMLDocReader r; - r.parse(reader); - m_rootNode = r.releaseRootNode(); - if (!m_rootNode) - m_rootNode = std::make_unique(YAML_MAPPING_NODE); - } else { - m_rootNode = std::make_unique(YAML_MAPPING_NODE); - } - - m_subStack.push_back(m_rootNode.get()); - if (!classType.empty()) { - auto classVal = std::make_unique(YAML_SCALAR_NODE); - classVal->m_scalarString.assign(classType); - m_rootNode->assignMapChild("DNAType", std::move(classVal)); - } -} - -YAMLDocWriter::~YAMLDocWriter() { yaml_emitter_delete(&m_emitter); } - -bool YAMLDocWriter::finish(athena::io::IStreamWriter* fout) { - const auto error = [this] { - HandleYAMLEmitterError(&m_emitter); - return false; - }; - - if (fout) { - yaml_emitter_set_output(&m_emitter, (yaml_write_handler_t*)YAMLAthenaWriter, fout); - } - if (!yaml_emitter_open(&m_emitter)) { - return error(); - } - - yaml_event_t event; - yaml_document_start_event_initialize(&event, nullptr, nullptr, nullptr, 1); - if (!yaml_emitter_emit(&m_emitter, &event)) { - return error(); - } - if (!RecursiveFinish(&m_emitter, *m_rootNode)) { - return false; - } - yaml_document_end_event_initialize(&event, 1); - if (!yaml_emitter_emit(&m_emitter, &event)) { - return error(); - } - - if (!yaml_emitter_close(&m_emitter) || !yaml_emitter_flush(&m_emitter)) { - return error(); - } - - return true; -} - -YAMLDocWriter::RecordRAII YAMLDocWriter::enterSubRecord(std::string_view name) { - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type != YAML_MAPPING_NODE && curSub->m_type != YAML_SEQUENCE_NODE) - return {}; - auto newNode = std::make_unique(YAML_MAPPING_NODE); - YAMLNode* newPtr = newNode.get(); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(!name.empty() ? name : std::string_view{}, std::move(newNode)); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.push_back(std::move(newNode)); - m_subStack.push_back(newPtr); - return RecordRAII{this}; -} - -void YAMLDocWriter::_leaveSubRecord() { - if (m_subStack.size() > 1) { - YAMLNode* curSub = m_subStack.back(); - /* Automatically lower to scalar or sequence if there's only one unnamed node */ - if (curSub->m_mapChildren.size() == 1 && curSub->m_mapChildren[0].first.empty()) { - auto& item = curSub->m_mapChildren[0]; - if (item.first.empty()) { - if (item.second->m_type == YAML_SCALAR_NODE) { - curSub->m_type = YAML_SCALAR_NODE; - curSub->m_scalarString = std::move(item.second->m_scalarString); - curSub->m_mapChildren.clear(); - } else if (item.second->m_type == YAML_SEQUENCE_NODE) { - curSub->m_type = YAML_SEQUENCE_NODE; - curSub->m_seqChildren = std::move(item.second->m_seqChildren); - curSub->m_mapChildren.clear(); - } - } - } - m_subStack.pop_back(); - } -} - -YAMLDocWriter::VectorRAII YAMLDocWriter::enterSubVector(std::string_view name) { - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type != YAML_MAPPING_NODE && curSub->m_type != YAML_SEQUENCE_NODE) - return {}; - auto newNode = std::make_unique(YAML_SEQUENCE_NODE); - YAMLNode* newPtr = newNode.get(); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(!name.empty() ? name : std::string_view{}, std::move(newNode)); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.push_back(std::move(newNode)); - m_subStack.push_back(newPtr); - return VectorRAII{this}; -} - -void YAMLDocWriter::_leaveSubVector() { - if (m_subStack.size() > 1) - m_subStack.pop_back(); -} - -template -void YAMLDocWriter::writeVal(std::string_view name, const INTYPE& val) { - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(!name.empty() ? name : std::string_view{}, ValToNode(val)); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.push_back(ValToNode(val)); -} - -template void YAMLDocWriter::writeVal(std::string_view name, const atInt8& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atUint8& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atInt16& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atUint16& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atInt32& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atUint32& val); -template void YAMLDocWriter::writeVal(std::string_view name, const float& val); -template void YAMLDocWriter::writeVal(std::string_view name, const double& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atVec3f& val); -template void YAMLDocWriter::writeVal(std::string_view name, const atVec4f& val); -template void YAMLDocWriter::writeVal(std::string_view name, const bool& val); - -template -void YAMLDocWriter::writeVal(std::string_view name, const INTYPE& val, size_t byteCount) { - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type == YAML_MAPPING_NODE) - curSub->assignMapChild(!name.empty() ? name : std::string_view{}, ValToNode(val, byteCount)); - else if (curSub->m_type == YAML_SEQUENCE_NODE) - curSub->m_seqChildren.push_back(ValToNode(val, byteCount)); -} - -void YAMLDocWriter::writeBool(std::string_view name, const bool& val) { writeVal(name, val); } - -void YAMLDocWriter::writeByte(std::string_view name, const atInt8& val) { writeVal(name, val); } - -void YAMLDocWriter::writeUByte(std::string_view name, const atUint8& val) { writeVal(name, val); } - -void YAMLDocWriter::writeInt16(std::string_view name, const atInt16& val) { writeVal(name, val); } - -void YAMLDocWriter::writeUint16(std::string_view name, const atUint16& val) { writeVal(name, val); } - -void YAMLDocWriter::writeInt32(std::string_view name, const atInt32& val) { writeVal(name, val); } - -void YAMLDocWriter::writeUint32(std::string_view name, const atUint32& val) { writeVal(name, val); } - -void YAMLDocWriter::writeInt64(std::string_view name, const atInt64& val) { writeVal(name, val); } - -void YAMLDocWriter::writeUint64(std::string_view name, const atUint64& val) { writeVal(name, val); } - -void YAMLDocWriter::writeFloat(std::string_view name, const float& val) { writeVal(name, val); } - -void YAMLDocWriter::writeDouble(std::string_view name, const double& val) { writeVal(name, val); } - -void YAMLDocWriter::writeVec2f(std::string_view name, const atVec2f& val) { writeVal(name, val); } - -void YAMLDocWriter::writeVec3f(std::string_view name, const atVec3f& val) { writeVal(name, val); } - -void YAMLDocWriter::writeVec4f(std::string_view name, const atVec4f& val) { writeVal(name, val); } - -void YAMLDocWriter::writeVec2d(std::string_view name, const atVec2d& val) { writeVal(name, val); } - -void YAMLDocWriter::writeVec3d(std::string_view name, const atVec3d& val) { writeVal(name, val); } - -void YAMLDocWriter::writeVec4d(std::string_view name, const atVec4d& val) { writeVal(name, val); } - -void YAMLDocWriter::writeUBytes(std::string_view name, const std::unique_ptr& val, size_t byteCount) { - writeVal&>(name, val, byteCount); -} - -void YAMLDocWriter::writeString(std::string_view name, std::string_view val) { writeVal(name, val); } - -void YAMLDocWriter::writeWString(std::string_view name, std::wstring_view val) { writeVal(name, val); } - -void YAMLDocWriter::writeU16String(std::string_view name, std::u16string_view val) { - writeVal(name, val); -} - -void YAMLDocWriter::writeU32String(std::string_view name, std::u32string_view val) { - writeVal(name, val); -} - -void YAMLDocWriter::setStyle(YAMLNodeStyle s) { m_subStack.back()->m_style = s; } - -static void InsertNode(std::vector& nodeStack, std::unique_ptr& mapKey, - std::unique_ptr& retVal, std::unique_ptr&& newNode) { - if (nodeStack.empty()) { - retVal = std::move(newNode); - return; - } - YAMLNode* parent = nodeStack.back(); - if (parent->m_type == YAML_SEQUENCE_NODE) { - parent->m_seqChildren.push_back(std::move(newNode)); - } else if (parent->m_type == YAML_MAPPING_NODE) { - if (!mapKey) - mapKey = std::move(newNode); - else { - parent->assignMapChild(mapKey->m_scalarString, std::move(newNode)); - mapKey.reset(nullptr); - } - } -} - -std::unique_ptr YAMLDocReader::ParseEvents(athena::io::IStreamReader* reader) { - yaml_event_t event; - if (reader) - yaml_parser_set_input(&m_parser, (yaml_read_handler_t*)YAMLAthenaReader, reader); - if (!yaml_parser_parse(&m_parser, &event)) { - HandleYAMLParserError(&m_parser); - return std::unique_ptr(); - } - - std::vector nodeStack; - std::unique_ptr mapKey; - std::unique_ptr retVal; - int result; - for (result = yaml_parser_parse(&m_parser, &event); event.type != YAML_STREAM_END_EVENT; - result = yaml_parser_parse(&m_parser, &event)) { - if (!result) { - HandleYAMLParserError(&m_parser); - return nullptr; - } - switch (event.type) { - case YAML_SCALAR_EVENT: { - if (nodeStack.empty()) { - atWarning(FMT_STRING("YAML parser stack empty; skipping scalar node")); - break; - } - auto newScalar = std::make_unique(YAML_SCALAR_NODE); - newScalar->m_scalarString.assign((char*)event.data.scalar.value, event.data.scalar.length); - if (nodeStack.empty()) - retVal = std::move(newScalar); - else - InsertNode(nodeStack, mapKey, retVal, std::move(newScalar)); - break; - } - case YAML_SEQUENCE_START_EVENT: { - YAMLNode* newSeq = new YAMLNode(YAML_SEQUENCE_NODE); - InsertNode(nodeStack, mapKey, retVal, std::unique_ptr(newSeq)); - nodeStack.push_back(newSeq); - break; - } - case YAML_SEQUENCE_END_EVENT: { - nodeStack.pop_back(); - break; - } - case YAML_MAPPING_START_EVENT: { - YAMLNode* newMap = new YAMLNode(YAML_MAPPING_NODE); - InsertNode(nodeStack, mapKey, retVal, std::unique_ptr(newMap)); - nodeStack.push_back(newMap); - break; - } - case YAML_MAPPING_END_EVENT: { - nodeStack.pop_back(); - break; - } - case YAML_DOCUMENT_END_EVENT: { - yaml_event_delete(&event); - return retVal; - } - default: - break; - } - yaml_event_delete(&event); - } - return std::unique_ptr(); -} - -YAMLDocReader::YAMLDocReader() { - if (!yaml_parser_initialize(&m_parser)) { - HandleYAMLParserError(&m_parser); - return; - } -} -YAMLDocReader::~YAMLDocReader() { yaml_parser_delete(&m_parser); } - -void YAMLDocReader::reset() { - yaml_parser_delete(&m_parser); - if (!yaml_parser_initialize(&m_parser)) - HandleYAMLParserError(&m_parser); -} - -bool YAMLDocReader::parse(athena::io::IStreamReader* reader) { - std::unique_ptr newRoot = ParseEvents(reader); - if (!newRoot) - return false; - m_rootNode = std::move(newRoot); - m_subStack.clear(); - m_subStack.push_back(m_rootNode.get()); - m_seqTrackerStack.clear(); - return true; -} - -bool YAMLDocReader::ClassTypeOperation(std::function func) { - yaml_event_t event; - if (!yaml_parser_parse(&m_parser, &event)) { - HandleYAMLParserError(&m_parser); - return false; - } - - int result; - int mappingLevel = 0; - bool inDNA = false; - for (result = yaml_parser_parse(&m_parser, &event); event.type != YAML_STREAM_END_EVENT; - result = yaml_parser_parse(&m_parser, &event)) { - if (!result) { - HandleYAMLParserError(&m_parser); - return false; - } - switch (event.type) { - case YAML_SCALAR_EVENT: { - if (mappingLevel == 1) { - if (inDNA) { - bool result = func(reinterpret_cast(event.data.scalar.value)); - yaml_event_delete(&event); - return result; - } - if (!strcmp("DNAType", reinterpret_cast(event.data.scalar.value))) - inDNA = true; - } - break; - } - case YAML_MAPPING_START_EVENT: { - ++mappingLevel; - inDNA = false; - break; - } - case YAML_MAPPING_END_EVENT: { - --mappingLevel; - inDNA = false; - break; - } - case YAML_DOCUMENT_END_EVENT: { - yaml_event_delete(&event); - return false; - } - default: - break; - } - yaml_event_delete(&event); - } - return false; -} - -bool YAMLDocReader::ValidateClassType(std::string_view expectedType) { - if (expectedType.empty()) - return false; - - return ClassTypeOperation([&](std::string_view dnaType) { return expectedType == dnaType; }); -} - -YAMLDocReader::RecordRAII YAMLDocReader::enterSubRecord(std::string_view name) { - YAMLNode* curSub = m_subStack.back(); - if (curSub->m_type == YAML_SEQUENCE_NODE) { - int& seqIdx = m_seqTrackerStack.back(); - m_subStack.push_back(curSub->m_seqChildren[seqIdx++].get()); - if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) - m_seqTrackerStack.push_back(0); - return RecordRAII{this}; - } else if (name.empty()) { - atError(FMT_STRING("Expected YAML sequence")); - } - for (const auto& item : curSub->m_mapChildren) { - if (item.first == name) { - m_subStack.push_back(item.second.get()); - if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) - m_seqTrackerStack.push_back(0); - return RecordRAII{this}; - } - } - return {}; -} - -void YAMLDocReader::_leaveSubRecord() { - if (m_subStack.size() > 1) { - if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE) - m_seqTrackerStack.pop_back(); - m_subStack.pop_back(); - } -} - -YAMLDocReader::VectorRAII YAMLDocReader::enterSubVector(std::string_view name, size_t& countOut) { - YAMLNode* curSub = m_subStack.back(); - if (name.empty() && curSub->m_type == YAML_SEQUENCE_NODE) { - m_subStack.push_back(curSub); - m_seqTrackerStack.push_back(0); - countOut = curSub->m_seqChildren.size(); - return VectorRAII{this}; - } else { - for (const auto& item : curSub->m_mapChildren) { - if (item.first == name) { - YAMLNode* nextSub = item.second.get(); - if (nextSub->m_type == YAML_SEQUENCE_NODE) { - countOut = nextSub->m_seqChildren.size(); - } else { - atError(FMT_STRING("'{}' is not a vector field"), name); - countOut = 0; - } - m_subStack.push_back(nextSub); - m_seqTrackerStack.push_back(0); - return VectorRAII{this}; - } - } - } - countOut = 0; - return {}; -} - -void YAMLDocReader::_leaveSubVector() { - if (m_subStack.size() > 1) { - m_subStack.pop_back(); - m_seqTrackerStack.pop_back(); - } -} - -template -RETURNTYPE YAMLDocReader::readVal(std::string_view name) { - if (m_subStack.size()) { - const YAMLNode* mnode = m_subStack.back(); - if (mnode->m_type == YAML_SCALAR_NODE) { - return NodeToVal(mnode); - } else if (mnode->m_type == YAML_SEQUENCE_NODE) { - int& seqIdx = m_seqTrackerStack.back(); - return NodeToVal(mnode->m_seqChildren[seqIdx++].get()); - } else if (mnode->m_type == YAML_MAPPING_NODE && !name.empty()) { - for (const auto& item : mnode->m_mapChildren) { - if (item.first == name) { - return NodeToVal(item.second.get()); - } - } - } - } - if (!name.empty()) - atWarning(FMT_STRING("Unable to find field '{}'; returning 0"), name); - return RETURNTYPE(); -} - -template atInt8 YAMLDocReader::readVal(std::string_view name); -template atUint8 YAMLDocReader::readVal(std::string_view name); -template atInt16 YAMLDocReader::readVal(std::string_view name); -template atUint16 YAMLDocReader::readVal(std::string_view name); -template atInt32 YAMLDocReader::readVal(std::string_view name); -template atUint32 YAMLDocReader::readVal(std::string_view name); -template float YAMLDocReader::readVal(std::string_view name); -template double YAMLDocReader::readVal(std::string_view name); -template atVec3f YAMLDocReader::readVal(std::string_view name); -template atVec4f YAMLDocReader::readVal(std::string_view name); -template bool YAMLDocReader::readVal(std::string_view name); - -bool YAMLDocReader::readBool(std::string_view name) { return readVal(name); } - -atInt8 YAMLDocReader::readByte(std::string_view name) { return readVal(name); } - -atUint8 YAMLDocReader::readUByte(std::string_view name) { return readVal(name); } - -atInt16 YAMLDocReader::readInt16(std::string_view name) { return readVal(name); } - -atUint16 YAMLDocReader::readUint16(std::string_view name) { return readVal(name); } - -atInt32 YAMLDocReader::readInt32(std::string_view name) { return readVal(name); } - -atUint32 YAMLDocReader::readUint32(std::string_view name) { return readVal(name); } - -atInt64 YAMLDocReader::readInt64(std::string_view name) { return readVal(name); } - -atUint64 YAMLDocReader::readUint64(std::string_view name) { return readVal(name); } - -float YAMLDocReader::readFloat(std::string_view name) { return readVal(name); } - -double YAMLDocReader::readDouble(std::string_view name) { return readVal(name); } - -atVec2f YAMLDocReader::readVec2f(std::string_view name) { return readVal(name); } - -atVec3f YAMLDocReader::readVec3f(std::string_view name) { return readVal(name); } -atVec4f YAMLDocReader::readVec4f(std::string_view name) { return readVal(name); } - -atVec2d YAMLDocReader::readVec2d(std::string_view name) { return readVal(name); } - -atVec3d YAMLDocReader::readVec3d(std::string_view name) { return readVal(name); } - -atVec4d YAMLDocReader::readVec4d(std::string_view name) { return readVal(name); } - -std::unique_ptr YAMLDocReader::readUBytes(std::string_view name) { - return readVal>(name); -} - -std::string YAMLDocReader::readString(std::string_view name) { return readVal(name); } - -std::wstring YAMLDocReader::readWString(std::string_view name) { return readVal(name); } - -static bool EmitKeyScalar(yaml_emitter_t* doc, std::string_view val) { - yaml_event_t event; - if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)val.data(), val.size(), true, true, - YAML_PLAIN_SCALAR_STYLE)) - return false; - return yaml_emitter_emit(doc, &event) != 0; -} - -static yaml_scalar_style_t ScalarStyle(const YAMLNode& node) { - for (const auto& ch : node.m_scalarString) - if (ch == '\n') - return YAML_LITERAL_SCALAR_STYLE; - return YAML_ANY_SCALAR_STYLE; -} - -static yaml_sequence_style_t SequenceStyle(const YAMLNode& node) { - if (node.m_style == YAMLNodeStyle::Flow) - return YAML_FLOW_SEQUENCE_STYLE; - else if (node.m_style == YAMLNodeStyle::Block) - return YAML_BLOCK_SEQUENCE_STYLE; - - size_t count = 0; - for (const auto& item : node.m_seqChildren) { - if (item->m_type != YAML_SCALAR_NODE) - return YAML_BLOCK_SEQUENCE_STYLE; - size_t strLen = item->m_scalarString.size(); - size_t thisCount = strLen / 10; - if (!thisCount) - thisCount = 1; - count += thisCount; - } - return (count > 6) ? YAML_BLOCK_SEQUENCE_STYLE : YAML_FLOW_SEQUENCE_STYLE; -} - -static yaml_mapping_style_t MappingStyle(const YAMLNode& node) { - if (node.m_style == YAMLNodeStyle::Flow) - return YAML_FLOW_MAPPING_STYLE; - else if (node.m_style == YAMLNodeStyle::Block) - return YAML_BLOCK_MAPPING_STYLE; - - size_t count = 0; - for (const auto& item : node.m_mapChildren) { - if (item.second->m_type != YAML_SCALAR_NODE) - return YAML_BLOCK_MAPPING_STYLE; - size_t strLen = item.second->m_scalarString.size(); - size_t thisCount = strLen / 10; - if (!thisCount) - thisCount = 1; - count += thisCount; - } - return (count > 6) ? YAML_BLOCK_MAPPING_STYLE : YAML_FLOW_MAPPING_STYLE; -} - -bool YAMLDocWriter::RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node) { - const auto handleError = [doc] { - HandleYAMLEmitterError(doc); - return false; - }; - - yaml_event_t event; - if (node.m_type == YAML_SCALAR_NODE) { - if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)node.m_scalarString.c_str(), - node.m_scalarString.length(), true, true, ScalarStyle(node)) || - !yaml_emitter_emit(doc, &event)) { - return handleError(); - } - } else if (node.m_type == YAML_SEQUENCE_NODE) { - if (!yaml_sequence_start_event_initialize(&event, nullptr, nullptr, 1, SequenceStyle(node)) || - !yaml_emitter_emit(doc, &event)) { - return handleError(); - } - for (const auto& item : node.m_seqChildren) { - if (!RecursiveFinish(doc, *item)) { - return handleError(); - } - } - if (!yaml_sequence_end_event_initialize(&event) || !yaml_emitter_emit(doc, &event)) { - return handleError(); - } - } else if (node.m_type == YAML_MAPPING_NODE) { - if (!yaml_mapping_start_event_initialize(&event, nullptr, nullptr, true, MappingStyle(node)) || - !yaml_emitter_emit(doc, &event)) { - return handleError(); - } - for (const auto& item : node.m_mapChildren) { - if (!EmitKeyScalar(doc, item.first.c_str())) { - return handleError(); - } - if (!RecursiveFinish(doc, *item.second)) { - return handleError(); - } - } - event.type = YAML_MAPPING_END_EVENT; - if (!yaml_mapping_end_event_initialize(&event) || !yaml_emitter_emit(doc, &event)) { - return handleError(); - } - } - return true; -} - -constexpr std::string_view base64_chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -static bool is_base64(unsigned char c) { return isalnum(c) || c == '+' || c == '/'; } - -std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len) { - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - ret.reserve(in_len * 4 / 3); - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (i = 0; (i < 4); i++) - ret += base64_chars[char_array_4[i]]; - i = 0; - } - } - - if (i) { - for (j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars[char_array_4[j]]; - - while ((i++ < 3)) - ret += '='; - } - - return ret; -} -std::unique_ptr base64_decode(std::string_view encoded_string) { - int in_len = encoded_string.size(); - int i = 0; - int j = 0; - int in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::unique_ptr ret(new atUint8[in_len * 3 / 4]); - atUint8* retBuf = ret.get(); - - while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; - in_++; - if (i == 4) { - for (i = 0; i < 4; i++) - char_array_4[i] = base64_chars.find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - *retBuf++ = char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j < 4; j++) - char_array_4[j] = 0; - - for (j = 0; j < 4; j++) - char_array_4[j] = base64_chars.find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) - *retBuf++ = char_array_3[j]; - } - - return ret; -} - -} // namespace athena::io diff --git a/src/athena/Dir.cpp b/src/athena/Dir.cpp index ca966b7..3033071 100644 --- a/src/athena/Dir.cpp +++ b/src/athena/Dir.cpp @@ -51,7 +51,7 @@ bool Dir::rm(std::string_view path) { return !(remove((m_path + "/" + path.data( bool Dir::touch() { std::srand(std::time(nullptr)); atUint64 tmp = utility::rand64(); - std::string tmpFile = fmt::format(FMT_STRING("{:016X}.tmp"), tmp); + std::string tmpFile = std::format("{:016X}.tmp", tmp); bool ret = FileInfo(m_path + "/" + tmpFile).touch(); if (ret) return rm(tmpFile); diff --git a/src/athena/FileReader.cpp b/src/athena/FileReader.cpp index b230168..9347e43 100644 --- a/src/athena/FileReader.cpp +++ b/src/athena/FileReader.cpp @@ -33,7 +33,7 @@ void FileReader::open() { if (!m_fileHandle) { std::string _filename = filename(); if (m_globalErr) - atError(FMT_STRING("File not found '{}'"), _filename); + atError("File not found '{}'", _filename); setError(); return; } @@ -47,7 +47,7 @@ void FileReader::open() { void FileReader::close() { if (!m_fileHandle) { if (m_globalErr) - atError(FMT_STRING("Cannot close an unopened stream")); + atError("Cannot close an unopened stream"); setError(); return; } @@ -76,7 +76,7 @@ void FileReader::seek(atInt64 pos, SeekOrigin origin) { } if (m_offset > length()) { if (m_globalErr) - atError(FMT_STRING("Unable to seek in file")); + atError("Unable to seek in file"); setError(); return; } @@ -89,7 +89,7 @@ void FileReader::seek(atInt64 pos, SeekOrigin origin) { } } else if (fseeko64(m_fileHandle, pos, int(origin)) != 0) { if (m_globalErr) - atError(FMT_STRING("Unable to seek in file")); + atError("Unable to seek in file"); setError(); } } @@ -97,7 +97,7 @@ void FileReader::seek(atInt64 pos, SeekOrigin origin) { atUint64 FileReader::position() const { if (!isOpen()) { if (m_globalErr) - atError(FMT_STRING("File not open")); + atError("File not open"); return 0; } @@ -110,7 +110,7 @@ atUint64 FileReader::position() const { atUint64 FileReader::length() const { if (!isOpen()) { if (m_globalErr) - atError(FMT_STRING("File not open")); + atError("File not open"); return 0; } @@ -120,7 +120,7 @@ atUint64 FileReader::length() const { atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) { if (!isOpen()) { if (m_globalErr) - atError(FMT_STRING("File not open for reading")); + atError("File not open for reading"); setError(); return 0; } diff --git a/src/athena/FileWriterNix.cpp b/src/athena/FileWriterNix.cpp index 81ec7d9..a583678 100644 --- a/src/athena/FileWriterNix.cpp +++ b/src/athena/FileWriterNix.cpp @@ -48,8 +48,9 @@ void FileWriter::open(bool overwrite) { } if (!m_fileHandle) { - if (m_globalErr) - atError(FMT_STRING("Unable to open file '%s'"), filename().c_str()); + if (m_globalErr) { + atError("Unable to open file '{}'", m_filename); + } setError(); return; } @@ -61,7 +62,7 @@ void FileWriter::open(bool overwrite) { void FileWriter::close() { if (!m_fileHandle) { if (m_globalErr) - atError(FMT_STRING("Cannot close an unopened stream")); + atError("Cannot close an unopened stream"); setError(); return; } @@ -81,14 +82,14 @@ void FileWriter::close() { void FileWriter::seek(atInt64 pos, SeekOrigin origin) { if (!isOpen()) { if (m_globalErr) - atError(FMT_STRING("Unable to seek in file, not open")); + atError("Unable to seek in file, not open"); setError(); return; } if (fseeko64(m_fileHandle, pos, int(origin)) != 0) { if (m_globalErr) - atError(FMT_STRING("Unable to seek in file")); + atError("Unable to seek in file"); setError(); } } @@ -100,14 +101,14 @@ atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } void FileWriter::writeUBytes(const atUint8* data, atUint64 len) { if (!isOpen()) { if (m_globalErr) - atError(FMT_STRING("File not open for writing")); + atError("File not open for writing"); setError(); return; } if (fwrite(data, 1, len, m_fileHandle) != len) { if (m_globalErr) - atError(FMT_STRING("Unable to write to stream")); + atError("Unable to write to stream"); setError(); } } diff --git a/src/athena/Global.cpp b/src/athena/Global.cpp index 8a9c565..1696b60 100644 --- a/src/athena/Global.cpp +++ b/src/athena/Global.cpp @@ -35,7 +35,7 @@ std::ostream& operator<<(std::ostream& os, const athena::Endian& endian) { } static void __defaultExceptionHandler(athena::error::Level level, const char* file, const char* function, int line, - fmt::string_view fmt, fmt::format_args args) { + std::string_view fmt, std::format_args args) { std::string levelStr; switch (level) { case athena::error::Level::Warning: @@ -51,7 +51,7 @@ static void __defaultExceptionHandler(athena::error::Level level, const char* fi break; } - std::string msg = fmt::vformat(fmt, args); + std::string msg = std::vformat(fmt, args); std::cerr << levelStr << " " << file << " " << function << "(" << line << "): " << msg << std::endl; } diff --git a/src/athena/MemoryReader.cpp b/src/athena/MemoryReader.cpp index bdbd3df..4727f77 100644 --- a/src/athena/MemoryReader.cpp +++ b/src/athena/MemoryReader.cpp @@ -13,7 +13,7 @@ MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership : m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) { if (!data) { if (m_globalErr) - atError(FMT_STRING("data cannot be NULL")); + atError("data cannot be NULL"); setError(); return; } @@ -27,7 +27,7 @@ MemoryReader::~MemoryReader() { MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) : MemoryReader(data, length, false) { if (!data) { if (m_globalErr) - atError(FMT_STRING("data cannot be NULL")); + atError("data cannot be NULL"); setError(); return; } @@ -42,7 +42,7 @@ void MemoryReader::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::Begin: if ((position < 0 || atInt64(position) > atInt64(m_length))) { if (m_globalErr) - atFatal(FMT_STRING("Position {:08X} outside stream bounds "), position); + atFatal("Position {:08X} outside stream bounds ", position); m_position = m_length; setError(); return; @@ -54,7 +54,7 @@ void MemoryReader::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::Current: if (((atInt64(m_position) + position) < 0 || (m_position + atUint64(position)) > m_length)) { if (m_globalErr) - atFatal(FMT_STRING("Position {:08X} outside stream bounds "), position); + atFatal("Position {:08X} outside stream bounds ", position); m_position = (position < 0 ? 0 : m_length); setError(); return; @@ -66,7 +66,7 @@ void MemoryReader::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::End: if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) { if (m_globalErr) - atFatal(FMT_STRING("Position {:08X} outside stream bounds "), position); + atFatal("Position {:08X} outside stream bounds ", position); m_position = m_length; setError(); return; @@ -104,7 +104,7 @@ atUint8* MemoryReader::data() const { atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) { if (m_position >= m_length) { if (m_globalErr) - atError(FMT_STRING("Position {:08X} outside stream bounds "), m_position); + atError("Position {:08X} outside stream bounds ", m_position); m_position = m_length; setError(); return 0; @@ -123,7 +123,7 @@ void MemoryCopyReader::loadData() { if (!in) { if (m_globalErr) - atError(FMT_STRING("Unable to open file '%s'"), m_filepath); + atError("Unable to open file '%s'", m_filepath); setError(); return; } @@ -145,7 +145,7 @@ void MemoryCopyReader::loadData() { if (ret < 0) { if (m_globalErr) - atError(FMT_STRING("Error reading data from disk")); + atError("Error reading data from disk"); setError(); return; } else if (ret == 0) diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index a825fd6..a3c6b2f 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -12,7 +12,7 @@ namespace athena::io { MemoryWriter::MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership) : m_data(data), m_length(length), m_bufferOwned(takeOwnership) { if (!data) { - atError(FMT_STRING("data cannot be NULL")); + atError("data cannot be NULL"); setError(); return; } @@ -32,7 +32,7 @@ MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length) { m_bufferOwned = false; if (length == 0) { - atError(FMT_STRING("length cannot be 0")); + atError("length cannot be 0"); setError(); return; } @@ -51,7 +51,7 @@ MemoryCopyWriter::MemoryCopyWriter(std::string_view filename) { m_bufferOwned = false; if (!m_data) { - atError(FMT_STRING("Could not allocate memory!")); + atError("Could not allocate memory!"); setError(); return; } @@ -61,13 +61,13 @@ void MemoryWriter::seek(atInt64 position, SeekOrigin origin) { switch (origin) { case SeekOrigin::Begin: if (position < 0) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } if ((atUint64)position > m_length) { - atError(FMT_STRING("data exceeds available buffer space")); + atError("data exceeds available buffer space"); setError(); return; } @@ -77,13 +77,13 @@ void MemoryWriter::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::Current: if ((((atInt64)m_position + position) < 0)) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } if (m_position + position > m_length) { - atError(FMT_STRING("data exceeds available buffer space")); + atError("data exceeds available buffer space"); setError(); return; } @@ -93,13 +93,13 @@ void MemoryWriter::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::End: if (((atInt64)m_length - position) < 0) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } if ((atUint64)position > m_length) { - atError(FMT_STRING("data exceeds available buffer space")); + atError("data exceeds available buffer space"); setError(); return; } @@ -113,7 +113,7 @@ void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) { switch (origin) { case SeekOrigin::Begin: if (position < 0) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } @@ -126,7 +126,7 @@ void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::Current: if ((((atInt64)m_position + position) < 0)) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } @@ -139,7 +139,7 @@ void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::End: if (((atInt64)m_length - position) < 0) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } @@ -180,7 +180,7 @@ atUint8* MemoryWriter::data() const { void MemoryWriter::save(std::string_view filename) { if (filename.empty() && m_filepath.empty()) { - atError(FMT_STRING("No file specified, cannot save.")); + atError("No file specified, cannot save."); setError(); return; } @@ -191,7 +191,7 @@ void MemoryWriter::save(std::string_view filename) { std::unique_ptr out{std::fopen(m_filepath.c_str(), "wb"), std::fclose}; if (!out) { - atError(FMT_STRING("Unable to open file '{}'"), m_filepath); + atError("Unable to open file '{}'", m_filepath); setError(); return; } @@ -207,7 +207,7 @@ void MemoryWriter::save(std::string_view filename) { const atInt64 ret = std::fwrite(m_data + done, 1, blocksize, out.get()); if (ret < 0) { - atError(FMT_STRING("Error writing data to disk")); + atError("Error writing data to disk"); setError(); return; } @@ -222,13 +222,13 @@ void MemoryWriter::save(std::string_view filename) { void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) { if (!data) { - atError(FMT_STRING("data cannnot be NULL")); + atError("data cannnot be NULL"); setError(); return; } if (m_position + length > m_length) { - atError(FMT_STRING("data length exceeds available buffer space")); + atError("data length exceeds available buffer space"); setError(); return; } @@ -240,7 +240,7 @@ void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) { void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) { if (!data) { - atError(FMT_STRING("data cannnot be NULL")); + atError("data cannnot be NULL"); setError(); return; } @@ -255,7 +255,7 @@ void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) { void MemoryCopyWriter::resize(atUint64 newSize) { if (newSize < m_length) { - atError(FMT_STRING("New size cannot be less to the old size.")); + atError("New size cannot be less to the old size."); return; } diff --git a/src/athena/SkywardSwordQuest.cpp b/src/athena/SkywardSwordQuest.cpp index f9604d2..69d0faa 100644 --- a/src/athena/SkywardSwordQuest.cpp +++ b/src/athena/SkywardSwordQuest.cpp @@ -1,7 +1,7 @@ #include "athena/SkywardSwordQuest.hpp" #include "athena/Checksums.hpp" #include "athena/Utility.hpp" -#include "utf8proc.h" +#include "athena/utf8proc.h" #include namespace athena { diff --git a/src/athena/Socket.cpp b/src/athena/Socket.cpp index bf74e50..af9f211 100644 --- a/src/athena/Socket.cpp +++ b/src/athena/Socket.cpp @@ -16,6 +16,7 @@ #endif #include "athena/Global.hpp" +#include namespace athena::net { @@ -84,7 +85,7 @@ bool Socket::openSocket() { m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_socket == -1) { - atError(FMT_STRING("Can't allocate socket")); + atError("Can't allocate socket"); return false; } @@ -138,13 +139,13 @@ bool Socket::openAndListen(const IPAddress& address, uint32_t port) { sockaddr_in addr = createAddress(address.toInteger(), port); if (bind(m_socket, reinterpret_cast(&addr), sizeof(addr)) == -1) { /* Not likely to happen, but... */ - atError(FMT_STRING("Failed to bind listener socket to port {}"), port); + atError("Failed to bind listener socket to port {}", port); return false; } if (::listen(m_socket, 0) == -1) { /* Oops, socket is deaf */ - atError(FMT_STRING("Failed to listen to port {}"), port); + atError("Failed to listen to port {}", port); return false; } @@ -163,8 +164,10 @@ Socket::EResult Socket::accept(Socket& remoteSocketOut, sockaddr_in& fromAddress if (remoteSocket == -1) { #ifndef _WIN32 EResult res = (errno == EAGAIN) ? EResult::Busy : EResult::Error; - if (res == EResult::Error) - atError(FMT_STRING("Failed to accept incoming connection: {}"), strerror(errno)); + if (res == EResult::Error) { + auto err = strerror(errno); + atError("Failed to accept incoming connection: {}", err); + } #else EResult res = LastWSAError(); if (res == EResult::Error) diff --git a/src/athena/SpriteFileReader.cpp b/src/athena/SpriteFileReader.cpp index 5a3711a..72eb236 100644 --- a/src/athena/SpriteFileReader.cpp +++ b/src/athena/SpriteFileReader.cpp @@ -51,7 +51,6 @@ Sakura::SpriteFile* SpriteFileReader::readFile() { // which require data to be 32 byte aligned, or it causes some issues. // It's also convenient to have this, for later expansion. atUint32 reserved = readUint32(); - UNUSED(reserved); // Next we have to load the textures // If we tried to add them one at a time to the sprite container diff --git a/src/athena/Utility.cpp b/src/athena/Utility.cpp index c4ac85d..0ee581a 100644 --- a/src/athena/Utility.cpp +++ b/src/athena/Utility.cpp @@ -167,7 +167,7 @@ std::string wideToUtf8(std::wstring_view src) { utf8proc_uint8_t mb[4]; utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); if (c < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while encoding")); + atWarning("invalid UTF-8 character while encoding"); return retval; } retval.append(reinterpret_cast(mb), c); @@ -183,7 +183,7 @@ std::wstring utf8ToWide(std::string_view src) { utf8proc_int32_t wc; utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); if (len < 0) { - atWarning(FMT_STRING("invalid UTF-8 character while decoding")); + atWarning("invalid UTF-8 character while decoding"); return retval; } buf += len; diff --git a/src/athena/VectorWriter.cpp b/src/athena/VectorWriter.cpp index f117416..e4c82ba 100644 --- a/src/athena/VectorWriter.cpp +++ b/src/athena/VectorWriter.cpp @@ -10,7 +10,7 @@ void VectorWriter::seek(atInt64 position, SeekOrigin origin) { switch (origin) { case SeekOrigin::Begin: if (position < 0) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } @@ -23,7 +23,7 @@ void VectorWriter::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::Current: if ((((atInt64)m_position + position) < 0)) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } @@ -36,13 +36,13 @@ void VectorWriter::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::End: if (((atInt64)m_data.size() - position) < 0) { - atError(FMT_STRING("Position outside stream bounds")); + atError("Position outside stream bounds"); setError(); return; } if ((atUint64)position > m_data.size()) { - atError(FMT_STRING("data exceeds vector size")); + atError("data exceeds vector size"); setError(); return; } @@ -54,7 +54,7 @@ void VectorWriter::seek(atInt64 position, SeekOrigin origin) { void VectorWriter::writeUBytes(const atUint8* data, atUint64 length) { if (!data) { - atError(FMT_STRING("data cannnot be NULL")); + atError("data cannnot be NULL"); setError(); return; } diff --git a/src/athena/WiiFile.cpp b/src/athena/WiiFile.cpp index db207d5..3bdd5dd 100644 --- a/src/athena/WiiFile.cpp +++ b/src/athena/WiiFile.cpp @@ -78,7 +78,7 @@ bool WiiFile::isFile() const { return (m_type == WiiFile::File); } void WiiFile::addChild(WiiFile* file) { if (!isDirectory()) { - atWarning("{} is not a directory", filename()); + atWarning("{} is not a directory", m_filename); return; } diff --git a/src/ec.cpp b/src/ec.cpp index f28ad8f..ce66a12 100644 --- a/src/ec.cpp +++ b/src/ec.cpp @@ -78,7 +78,7 @@ static void square(atUint8* d, const atUint8* a) { static void itInvert(atUint8* d, const atUint8* a, const atUint8* b, atUint32 j) { atUint8 t[30]; - memcpy(t, a, 32); + memcpy(t, a, 30); while (j--) { square(d, t); memcpy(t, d, 30);