mirror of
https://github.com/libAthena/athena.git
synced 2025-12-08 13:15:05 +00:00
Remove atdna and fmt
This commit is contained in:
@@ -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 <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#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 <Endian DNAE>
|
||||
struct DNA {
|
||||
/**
|
||||
* @brief Designated byte-order used for serializing fields
|
||||
*/
|
||||
static constexpr Endian DNAEndian = DNAE;
|
||||
|
||||
/**
|
||||
* @brief Template type signaling atdna to capture the value where it's used
|
||||
* @tparam T The type of the value. Can be any numeric type or atVec* type
|
||||
* @tparam VE Endianness of the value
|
||||
*/
|
||||
template <typename T, Endian VE = DNAE>
|
||||
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 <typename T, size_t cntVar, Endian VE = DNAE>
|
||||
using Vector = std::vector<T>;
|
||||
|
||||
/**
|
||||
* @brief Template type wrapping std::unique_ptr<atUint8[]> 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 <size_t sizeVar>
|
||||
using Buffer = std::unique_ptr<atUint8[]>;
|
||||
|
||||
/**
|
||||
* @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 <atInt32 sizeVar = -1>
|
||||
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 <atInt32 sizeVar = -1, Endian VE = DNAE>
|
||||
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 <off_t offset, SeekOrigin direction>
|
||||
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 <size_t align>
|
||||
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<PropType::None>;
|
||||
using Write = athena::io::Write<PropType::None>;
|
||||
using BinarySize = athena::io::BinarySize<PropType::None>;
|
||||
using PropCount = athena::io::PropCount<PropType::None>;
|
||||
using ReadYaml = athena::io::ReadYaml<PropType::None>;
|
||||
using WriteYaml = athena::io::WriteYaml<PropType::None>;
|
||||
};
|
||||
|
||||
/**
|
||||
* @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<Read>(typename Read::StreamT& r)
|
||||
* { (Do stuff with `r`) }
|
||||
*/
|
||||
template <Endian DNAE>
|
||||
struct DNAV : DNA<DNAE> {
|
||||
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 <Endian DNAE>
|
||||
struct DNAVYaml : DNAV<DNAE> {
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "athena/DNA.hpp"
|
||||
#include "athena/FileReader.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
#include "athena/YAMLDocReader.hpp"
|
||||
#include "athena/YAMLDocWriter.hpp"
|
||||
|
||||
namespace athena::io {
|
||||
|
||||
template <class T>
|
||||
std::string_view __GetDNAName(const T& dna) {
|
||||
if constexpr (__IsDNAVRecord_v<T>) {
|
||||
return dna.DNATypeV();
|
||||
} else {
|
||||
return dna.DNAType();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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 <class T>
|
||||
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 <class DNASubtype>
|
||||
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 <class T>
|
||||
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 <class T>
|
||||
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 <class T>
|
||||
bool FromYAMLStream(T& dna, athena::io::IStreamReader& fin) {
|
||||
YAMLDocReader docReader;
|
||||
if (!docReader.parse(&fin))
|
||||
return false;
|
||||
dna.read(docReader);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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 <class T, typename NameT>
|
||||
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 <class DNASubtype>
|
||||
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
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <ostream>
|
||||
#include "athena/Types.hpp"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <format>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996)
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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 <Endian DNAE>
|
||||
struct DNA;
|
||||
template <Endian DNAE>
|
||||
struct DNAV;
|
||||
|
||||
template <class T>
|
||||
using __IsDNARecord = std::disjunction<std::is_base_of<DNA<Endian::Big>, T>, std::is_base_of<DNA<Endian::Little>, T>>;
|
||||
template <class T>
|
||||
constexpr bool __IsDNARecord_v = __IsDNARecord<T>::value;
|
||||
|
||||
template <class T>
|
||||
using __IsDNAVRecord =
|
||||
std::disjunction<std::is_base_of<DNAV<Endian::Big>, T>, std::is_base_of<DNAV<Endian::Little>, T>>;
|
||||
template <class T>
|
||||
constexpr bool __IsDNAVRecord_v = __IsDNAVRecord<T>::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 <typename First, typename... Rest>
|
||||
constexpr auto __FIRST_ARG__(First first, Rest...) { return first; }
|
||||
template <typename S, typename... Args>
|
||||
auto __make_args_checked__(const S& format_str, Args&&... args) {
|
||||
return fmt::make_args_checked<Args...>(format_str, std::forward<Args>(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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -61,12 +61,6 @@ public:
|
||||
|
||||
RecordRAII enterSubRecord(std::string_view name = {});
|
||||
|
||||
template <class T>
|
||||
void enumerate(std::string_view name, T& record, std::enable_if_t<__IsDNARecord_v<T>>* = nullptr) {
|
||||
if (auto rec = enterSubRecord(name))
|
||||
record.read(*this);
|
||||
}
|
||||
|
||||
class VectorRAII {
|
||||
friend class YAMLDocReader;
|
||||
YAMLDocReader* m_r = nullptr;
|
||||
|
||||
@@ -47,12 +47,6 @@ public:
|
||||
|
||||
RecordRAII enterSubRecord(std::string_view name = {});
|
||||
|
||||
template <class T>
|
||||
void enumerate(std::string_view name, T& record, std::enable_if_t<__IsDNARecord_v<T>>* = nullptr) {
|
||||
if (auto rec = enterSubRecord(name))
|
||||
record.write(*this);
|
||||
}
|
||||
|
||||
class VectorRAII {
|
||||
friend class YAMLDocWriter;
|
||||
YAMLDocWriter* m_w = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user