From d96d0d613806fd8d56eb8ae38bc41b89754f03de Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Fri, 2 Aug 2024 20:11:48 +0200 Subject: [MHR-??] [META] refactor code. Signed-off-by: Amlal EL Mahrouss --- NDKKit/AsmKit/AsmKit.hpp | 217 ---- NDKKit/AsmKit/AsmKit.hxx | 217 ++++ NDKKit/AsmKit/CPU/32x0.hpp | 95 -- NDKKit/AsmKit/CPU/32x0.hxx | 95 ++ NDKKit/AsmKit/CPU/64x0.hpp | 108 -- NDKKit/AsmKit/CPU/64x0.hxx | 108 ++ NDKKit/AsmKit/CPU/amd64.hpp | 57 - NDKKit/AsmKit/CPU/amd64.hxx | 57 + NDKKit/AsmKit/CPU/arm64.hpp | 26 - NDKKit/AsmKit/CPU/arm64.hxx | 26 + NDKKit/AsmKit/CPU/ppc.hpp | 1929 ------------------------------- NDKKit/AsmKit/CPU/ppc.hxx | 1929 +++++++++++++++++++++++++++++++ NDKKit/Defines.hpp | 147 --- NDKKit/Defines.hxx | 147 +++ NDKKit/Macros.hpp | 33 - NDKKit/Macros.hxx | 33 + NDKKit/NFC/AE.hpp | 143 --- NDKKit/NFC/AE.hxx | 143 +++ NDKKit/NFC/ELF.hpp | 389 ------- NDKKit/NFC/ELF.hxx | 389 +++++++ NDKKit/NFC/ErrorID.hpp | 22 - NDKKit/NFC/ErrorID.hxx | 22 + NDKKit/NFC/ErrorOr.hpp | 61 - NDKKit/NFC/ErrorOr.hxx | 61 + NDKKit/NFC/PEF.hpp | 134 --- NDKKit/NFC/PEF.hxx | 134 +++ NDKKit/NFC/Ref.hpp | 97 -- NDKKit/NFC/Ref.hxx | 97 ++ NDKKit/NFC/String.hpp | 90 -- NDKKit/NFC/String.hxx | 90 ++ NDKKit/NFC/XCOFF.hxx | 2 +- NDKKit/Parser.hpp | 178 --- NDKKit/Parser.hxx | 178 +++ NDKKit/Sources/32asm.cxx | 8 +- NDKKit/Sources/64asm.cxx | 8 +- NDKKit/Sources/64x0-cc.cxx | 8 +- NDKKit/Sources/AssemblyFactory.cxx | 4 +- NDKKit/Sources/Detail/asmutils.hxx | 4 +- NDKKit/Sources/Detail/compilerutils.hxx | 4 +- NDKKit/Sources/String.cxx | 2 +- NDKKit/Sources/bpp.cxx | 4 +- NDKKit/Sources/coff2ae.cxx | 6 +- NDKKit/Sources/cplusplus.cxx | 6 +- NDKKit/Sources/elf2ae.cxx | 6 +- NDKKit/Sources/i64asm.cxx | 8 +- NDKKit/Sources/link.cxx | 14 +- NDKKit/Sources/power-as.cxx | 12 +- NDKKit/Sources/power-cc.cxx | 8 +- NDKKit/UUID.hpp | 983 ---------------- NDKKit/UUID.hxx | 983 ++++++++++++++++ NDKKit/Version.hpp | 4 - NDKKit/Version.hxx | 4 + 52 files changed, 4765 insertions(+), 4765 deletions(-) delete mode 100644 NDKKit/AsmKit/AsmKit.hpp create mode 100644 NDKKit/AsmKit/AsmKit.hxx delete mode 100644 NDKKit/AsmKit/CPU/32x0.hpp create mode 100644 NDKKit/AsmKit/CPU/32x0.hxx delete mode 100644 NDKKit/AsmKit/CPU/64x0.hpp create mode 100644 NDKKit/AsmKit/CPU/64x0.hxx delete mode 100644 NDKKit/AsmKit/CPU/amd64.hpp create mode 100644 NDKKit/AsmKit/CPU/amd64.hxx delete mode 100644 NDKKit/AsmKit/CPU/arm64.hpp create mode 100644 NDKKit/AsmKit/CPU/arm64.hxx delete mode 100644 NDKKit/AsmKit/CPU/ppc.hpp create mode 100644 NDKKit/AsmKit/CPU/ppc.hxx delete mode 100644 NDKKit/Defines.hpp create mode 100644 NDKKit/Defines.hxx delete mode 100644 NDKKit/Macros.hpp create mode 100644 NDKKit/Macros.hxx delete mode 100644 NDKKit/NFC/AE.hpp create mode 100644 NDKKit/NFC/AE.hxx delete mode 100644 NDKKit/NFC/ELF.hpp create mode 100644 NDKKit/NFC/ELF.hxx delete mode 100644 NDKKit/NFC/ErrorID.hpp create mode 100644 NDKKit/NFC/ErrorID.hxx delete mode 100644 NDKKit/NFC/ErrorOr.hpp create mode 100644 NDKKit/NFC/ErrorOr.hxx delete mode 100644 NDKKit/NFC/PEF.hpp create mode 100644 NDKKit/NFC/PEF.hxx delete mode 100644 NDKKit/NFC/Ref.hpp create mode 100644 NDKKit/NFC/Ref.hxx delete mode 100644 NDKKit/NFC/String.hpp create mode 100644 NDKKit/NFC/String.hxx delete mode 100644 NDKKit/Parser.hpp create mode 100644 NDKKit/Parser.hxx delete mode 100644 NDKKit/UUID.hpp create mode 100644 NDKKit/UUID.hxx delete mode 100644 NDKKit/Version.hpp create mode 100644 NDKKit/Version.hxx diff --git a/NDKKit/AsmKit/AsmKit.hpp b/NDKKit/AsmKit/AsmKit.hpp deleted file mode 100644 index 6074efc..0000000 --- a/NDKKit/AsmKit/AsmKit.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include -#include -#include - -namespace CompilerKit -{ - // - // @brief Frontend to Assembly mountpoint. - // - class AssemblyInterface - { - public: - explicit AssemblyInterface() = default; - virtual ~AssemblyInterface() = default; - - MPCC_COPY_DEFAULT(AssemblyInterface); - - //@ brief compile to object file. - // Example C++ -> MASM -> AE object. - virtual Int32 CompileToFormat(std::string& src, Int32 arch) = 0; - }; - - /// @brief Simple assembly factory - class AssemblyFactory final - { - public: - explicit AssemblyFactory() = default; - ~AssemblyFactory() = default; - - MPCC_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchPowerPC, - kArchUnknown, - }; - - Int32 Compile(std::string& sourceFile, const Int32& arch) noexcept; - - void Mount(AssemblyInterface* mountPtr) noexcept; - AssemblyInterface* Unmount() noexcept; - - private: - AssemblyInterface* fMounted{nullptr}; - }; - - union NumberCastBase { - NumberCastBase() = default; - ~NumberCastBase() = default; - }; - - union NumberCast64 final { - NumberCast64() = default; - explicit NumberCast64(UInt64 raw) - : raw(raw) - { - } - ~NumberCast64() - { - raw = 0; - } - - CharType number[8]; - UInt64 raw; - }; - - union NumberCast32 final { - NumberCast32() = default; - explicit NumberCast32(UInt32 raw) - : raw(raw) - { - } - ~NumberCast32() - { - raw = 0; - } - - CharType number[4]; - UInt32 raw; - }; - - union NumberCast16 final { - NumberCast16() = default; - explicit NumberCast16(UInt16 raw) - : raw(raw) - { - } - ~NumberCast16() - { - raw = 0; - } - - CharType number[2]; - UInt16 raw; - }; - - union NumberCast8 final { - NumberCast8() = default; - explicit NumberCast8(UInt8 raw) - : raw(raw) - { - } - ~NumberCast8() - { - raw = 0; - } - - CharType number; - UInt8 raw; - }; - - class EncoderInterface - { - public: - explicit EncoderInterface() = default; - virtual ~EncoderInterface() = default; - - MPCC_COPY_DEFAULT(EncoderInterface); - - virtual std::string CheckLine(std::string& line, const std::string& file) = 0; - virtual bool WriteLine(std::string& line, const std::string& file) = 0; - virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) = 0; - }; - -#ifdef __ASM_NEED_AMD64__ - - class EncoderAMD64 final : public EncoderInterface - { - public: - explicit EncoderAMD64() = default; - ~EncoderAMD64() override = default; - - MPCC_COPY_DEFAULT(EncoderAMD64); - - virtual std::string CheckLine(std::string& line, - const std::string& file) override; - virtual bool WriteLine(std::string& line, const std::string& file) override; - virtual bool WriteNumber(const std::size_t& pos, - std::string& from_what) override; - - virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what); - virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what); - virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what); - }; - -#endif // __ASM_NEED_AMD64__ - -#ifdef __ASM_NEED_64x0__ - - class Encoder64x0 final : public EncoderInterface - { - public: - explicit Encoder64x0() = default; - ~Encoder64x0() override = default; - - MPCC_COPY_DEFAULT(Encoder64x0); - - virtual std::string CheckLine(std::string& line, - const std::string& file) override; - virtual bool WriteLine(std::string& line, const std::string& file) override; - virtual bool WriteNumber(const std::size_t& pos, - std::string& from_what) override; - }; - -#endif // __ASM_NEED_64x0__ - -#ifdef __ASM_NEED_32x0__ - - class Encoder32x0 final : public EncoderInterface - { - public: - explicit Encoder32x0() = default; - ~Encoder32x0() override = default; - - MPCC_COPY_DEFAULT(Encoder32x0); - - virtual std::string CheckLine(std::string& line, - const std::string& file) override; - virtual bool WriteLine(std::string& line, const std::string& file) override; - virtual bool WriteNumber(const std::size_t& pos, - std::string& from_what) override; - }; - -#endif // __ASM_NEED_32x0__ - -#ifdef __ASM_NEED_PPC__ - - class EncoderPowerPC final : public EncoderInterface - { - public: - explicit EncoderPowerPC() = default; - ~EncoderPowerPC() override = default; - - MPCC_COPY_DEFAULT(EncoderPowerPC); - - virtual std::string CheckLine(std::string& line, - const std::string& file) override; - virtual bool WriteLine(std::string& line, const std::string& file) override; - virtual bool WriteNumber(const std::size_t& pos, - std::string& from_what) override; - }; - -#endif // __ASM_NEED_32x0__ -} // namespace CompilerKit diff --git a/NDKKit/AsmKit/AsmKit.hxx b/NDKKit/AsmKit/AsmKit.hxx new file mode 100644 index 0000000..f6e67f2 --- /dev/null +++ b/NDKKit/AsmKit/AsmKit.hxx @@ -0,0 +1,217 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyInterface + { + public: + explicit AssemblyInterface() = default; + virtual ~AssemblyInterface() = default; + + MPCC_COPY_DEFAULT(AssemblyInterface); + + //@ brief compile to object file. + // Example C++ -> MASM -> AE object. + virtual Int32 CompileToFormat(std::string& src, Int32 arch) = 0; + }; + + /// @brief Simple assembly factory + class AssemblyFactory final + { + public: + explicit AssemblyFactory() = default; + ~AssemblyFactory() = default; + + MPCC_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchPowerPC, + kArchUnknown, + }; + + Int32 Compile(std::string& sourceFile, const Int32& arch) noexcept; + + void Mount(AssemblyInterface* mountPtr) noexcept; + AssemblyInterface* Unmount() noexcept; + + private: + AssemblyInterface* fMounted{nullptr}; + }; + + union NumberCastBase { + NumberCastBase() = default; + ~NumberCastBase() = default; + }; + + union NumberCast64 final { + NumberCast64() = default; + explicit NumberCast64(UInt64 raw) + : raw(raw) + { + } + ~NumberCast64() + { + raw = 0; + } + + CharType number[8]; + UInt64 raw; + }; + + union NumberCast32 final { + NumberCast32() = default; + explicit NumberCast32(UInt32 raw) + : raw(raw) + { + } + ~NumberCast32() + { + raw = 0; + } + + CharType number[4]; + UInt32 raw; + }; + + union NumberCast16 final { + NumberCast16() = default; + explicit NumberCast16(UInt16 raw) + : raw(raw) + { + } + ~NumberCast16() + { + raw = 0; + } + + CharType number[2]; + UInt16 raw; + }; + + union NumberCast8 final { + NumberCast8() = default; + explicit NumberCast8(UInt8 raw) + : raw(raw) + { + } + ~NumberCast8() + { + raw = 0; + } + + CharType number; + UInt8 raw; + }; + + class EncoderInterface + { + public: + explicit EncoderInterface() = default; + virtual ~EncoderInterface() = default; + + MPCC_COPY_DEFAULT(EncoderInterface); + + virtual std::string CheckLine(std::string& line, const std::string& file) = 0; + virtual bool WriteLine(std::string& line, const std::string& file) = 0; + virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) = 0; + }; + +#ifdef __ASM_NEED_AMD64__ + + class EncoderAMD64 final : public EncoderInterface + { + public: + explicit EncoderAMD64() = default; + ~EncoderAMD64() override = default; + + MPCC_COPY_DEFAULT(EncoderAMD64); + + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; + + virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what); + }; + +#endif // __ASM_NEED_AMD64__ + +#ifdef __ASM_NEED_64x0__ + + class Encoder64x0 final : public EncoderInterface + { + public: + explicit Encoder64x0() = default; + ~Encoder64x0() override = default; + + MPCC_COPY_DEFAULT(Encoder64x0); + + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; + }; + +#endif // __ASM_NEED_64x0__ + +#ifdef __ASM_NEED_32x0__ + + class Encoder32x0 final : public EncoderInterface + { + public: + explicit Encoder32x0() = default; + ~Encoder32x0() override = default; + + MPCC_COPY_DEFAULT(Encoder32x0); + + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; + }; + +#endif // __ASM_NEED_32x0__ + +#ifdef __ASM_NEED_PPC__ + + class EncoderPowerPC final : public EncoderInterface + { + public: + explicit EncoderPowerPC() = default; + ~EncoderPowerPC() override = default; + + MPCC_COPY_DEFAULT(EncoderPowerPC); + + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; + }; + +#endif // __ASM_NEED_32x0__ +} // namespace CompilerKit diff --git a/NDKKit/AsmKit/CPU/32x0.hpp b/NDKKit/AsmKit/CPU/32x0.hpp deleted file mode 100644 index 7fa02ad..0000000 --- a/NDKKit/AsmKit/CPU/32x0.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -// @brief 32x0 support. -// @file CPU/32x0.hpp - -#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ - {.fName = __NAME, \ - .fOpcode = __OPCODE, \ - .fFunct3 = __FUNCT3, \ - .fFunct7 = __FUNCT7}, - -#define kAsmImmediate 0x01 -#define kAsmSyscall 0x02 -#define kAsmJump 0x03 -#define kAsmNoArgs 0x04 - -#define kAsmByte 0 -#define kAsmHWord 1 -#define kAsmWord 2 - -struct CpuCode32x0 -{ - const char fName[32]; - char fOpcode; - char fSize; - char fFunct3; - char fFunct7; -}; - -#define kAsmDWordStr ".dword" /* 64 bit */ -#define kAsmWordStr ".word" /* 32-bit */ -#define kAsmHWordStr ".half" /* 16-bit */ -#define kAsmByteStr ".byte" /* 8-bit */ - -inline std::vector kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. - kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch - kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers - kAsmOpcodeDecl("psh", 0b0111011, 0b000, kAsmImmediate) // push to sp - kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. - kAsmOpcodeDecl("cls", 0b0111011, 0b010, - kAsmImmediate) // setup stack and call, store address to CR. - kAsmOpcodeDecl("rts", 0b0111011, 0b110, - kAsmImmediate) // pull stack and return form CR. - kAsmOpcodeDecl("int", 0b0111111, 0b000, kAsmSyscall) // raise interrupt -}; - -// \brief 64x0 register prefix -// example: r32, r0 -// r32 -> sp -// r0 -> hw zero - -#define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 16 -#define kAsmPcRegister 17 -#define kAsmCrRegister 18 -#define kAsmSpRegister 5 - -/* return address register */ -#define kAsmRetRegister 19 - -///////////////////////////////////////////////////////////////////////////// - -// SYSTEM CALL ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | OFF | - -// IMMEDIATE ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | - -// REG TO REG ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | - -//////////////////////////////// - -// LOAD/CALL INTERRUPTS - -// SET A HANDLER IN ADDRESS: TODO: find one -// DISABLE INTERRUPTS -// PROCESS INTERRUPT -// ENABLE INTERRUPTS - -//////////////////////////////// diff --git a/NDKKit/AsmKit/CPU/32x0.hxx b/NDKKit/AsmKit/CPU/32x0.hxx new file mode 100644 index 0000000..a24d17e --- /dev/null +++ b/NDKKit/AsmKit/CPU/32x0.hxx @@ -0,0 +1,95 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +// @brief 32x0 support. +// @file CPU/32x0.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + {.fName = __NAME, \ + .fOpcode = __OPCODE, \ + .fFunct3 = __FUNCT3, \ + .fFunct7 = __FUNCT7}, + +#define kAsmImmediate 0x01 +#define kAsmSyscall 0x02 +#define kAsmJump 0x03 +#define kAsmNoArgs 0x04 + +#define kAsmByte 0 +#define kAsmHWord 1 +#define kAsmWord 2 + +struct CpuCode32x0 +{ + const char fName[32]; + char fOpcode; + char fSize; + char fFunct3; + char fFunct7; +}; + +#define kAsmDWordStr ".dword" /* 64 bit */ +#define kAsmWordStr ".word" /* 32-bit */ +#define kAsmHWordStr ".half" /* 16-bit */ +#define kAsmByteStr ".byte" /* 8-bit */ + +inline std::vector kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. + kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch + kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers + kAsmOpcodeDecl("psh", 0b0111011, 0b000, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. + kAsmOpcodeDecl("cls", 0b0111011, 0b010, + kAsmImmediate) // setup stack and call, store address to CR. + kAsmOpcodeDecl("rts", 0b0111011, 0b110, + kAsmImmediate) // pull stack and return form CR. + kAsmOpcodeDecl("int", 0b0111111, 0b000, kAsmSyscall) // raise interrupt +}; + +// \brief 64x0 register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 16 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: TODO: find one +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +//////////////////////////////// diff --git a/NDKKit/AsmKit/CPU/64x0.hpp b/NDKKit/AsmKit/CPU/64x0.hpp deleted file mode 100644 index 3bd1f80..0000000 --- a/NDKKit/AsmKit/CPU/64x0.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include -#include - -// @brief 64x0 support. -// @file CPU/64x0.hpp - -#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ - {.fName = __NAME, \ - .fOpcode = __OPCODE, \ - .fFunct3 = __FUNCT3, \ - .fFunct7 = __FUNCT7}, - -#define kAsmImmediate 0x01 -#define kAsmRegToReg 0x02 -#define kAsmSyscall 0x03 -#define kAsmJump 0x04 -#define kAsmNoArgs 0x00 - -typedef char e64k_character_t; -typedef uint8_t e64k_num_t; - -struct CpuOpcode64x0 -{ - const e64k_character_t fName[32]; - e64k_num_t fOpcode; - e64k_num_t fFunct3; - e64k_num_t fFunct7; -}; - -inline std::vector kOpcodes64x0 = { - kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. - kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. - kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, - kAsmJump) // jump to linked return register - kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, - kAsmJump) // jump from return register. - kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) - kAsmOpcodeDecl("bg", 0b1100111, 0b111, kAsmRegToReg) - kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg) - kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg) - kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg) - kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg) - kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg) - kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate) - kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate) - kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate) - kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate) - // add/sub without carry flag - kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) - kAsmOpcodeDecl("sub", 0b0101011, 0b101, kAsmImmediate) - // add/sub with carry flag - kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate) - kAsmOpcodeDecl("decc", 0b0101011, 0b111, kAsmImmediate) - kAsmOpcodeDecl("int", 0b1110011, 0b00, kAsmSyscall) - kAsmOpcodeDecl("pha", 0b1110011, 0b00, kAsmNoArgs) - kAsmOpcodeDecl("pla", 0b1110011, 0b01, kAsmNoArgs)}; - -// \brief 64x0 register prefix -// example: r32, r0 -// r32 -> sp -// r0 -> hw zero - -#define kAsmFloatZeroRegister 0 -#define kAsmZeroRegister 0 - -#define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 30 -#define kAsmPcRegister 17 -#define kAsmCrRegister 18 -#define kAsmSpRegister 5 - -/* return address register */ -#define kAsmRetRegister 19 - -///////////////////////////////////////////////////////////////////////////// - -// SYSTEM CALL/JUMP ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | OFF | - -// IMMEDIATE ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | - -// REG TO REG ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | - -//////////////////////////////// - -// LOAD/CALL INTERRUPTS - -// SET A HANDLER IN ADDRESS: -// DISABLE INTERRUPTS -// PROCESS INTERRUPT -// ENABLE INTERRUPTS - -//////////////////////////////// diff --git a/NDKKit/AsmKit/CPU/64x0.hxx b/NDKKit/AsmKit/CPU/64x0.hxx new file mode 100644 index 0000000..d632fcc --- /dev/null +++ b/NDKKit/AsmKit/CPU/64x0.hxx @@ -0,0 +1,108 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include +#include + +// @brief 64x0 support. +// @file CPU/64x0.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + {.fName = __NAME, \ + .fOpcode = __OPCODE, \ + .fFunct3 = __FUNCT3, \ + .fFunct7 = __FUNCT7}, + +#define kAsmImmediate 0x01 +#define kAsmRegToReg 0x02 +#define kAsmSyscall 0x03 +#define kAsmJump 0x04 +#define kAsmNoArgs 0x00 + +typedef char e64k_character_t; +typedef uint8_t e64k_num_t; + +struct CpuOpcode64x0 +{ + const e64k_character_t fName[32]; + e64k_num_t fOpcode; + e64k_num_t fFunct3; + e64k_num_t fFunct7; +}; + +inline std::vector kOpcodes64x0 = { + kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. + kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. + kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, + kAsmJump) // jump to linked return register + kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, + kAsmJump) // jump from return register. + kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("bg", 0b1100111, 0b111, kAsmRegToReg) + kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg) + kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg) + kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg) + kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg) + kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate) + kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate) + // add/sub without carry flag + kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) + kAsmOpcodeDecl("sub", 0b0101011, 0b101, kAsmImmediate) + // add/sub with carry flag + kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate) + kAsmOpcodeDecl("decc", 0b0101011, 0b111, kAsmImmediate) + kAsmOpcodeDecl("int", 0b1110011, 0b00, kAsmSyscall) + kAsmOpcodeDecl("pha", 0b1110011, 0b00, kAsmNoArgs) + kAsmOpcodeDecl("pla", 0b1110011, 0b01, kAsmNoArgs)}; + +// \brief 64x0 register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmFloatZeroRegister 0 +#define kAsmZeroRegister 0 + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 30 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL/JUMP ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +//////////////////////////////// diff --git a/NDKKit/AsmKit/CPU/amd64.hpp b/NDKKit/AsmKit/CPU/amd64.hpp deleted file mode 100644 index 3edd5ca..0000000 --- a/NDKKit/AsmKit/CPU/amd64.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -// @brief AMD64 support. -// @file CPU/amd64.hpp - -#define kAsmOpcodeDecl(__NAME, __OPCODE) {.fName = __NAME, .fOpcode = __OPCODE}, - -typedef char i64_character_t; -typedef uint8_t i64_byte_t; -typedef uint16_t i64_hword_t; -typedef uint32_t i64_word_t; - -struct CpuOpcodeAMD64 -{ - std::string fName; - i64_byte_t fPrefixBytes[4]; - i64_hword_t fOpcode; - i64_hword_t fModReg; - i64_word_t fDisplacment; - i64_word_t fImmediate; -}; - -/// these two are edge cases -#define kAsmIntOpcode 0xCC -#define kasmIntOpcodeAlt 0xCD - -#define kAsmJumpOpcode 0x0F80 -#define kJumpLimit 30 -#define kJumpLimitStandard 0xE3 -#define kJumpLimitStandardLimit 0xEB - -inline std::vector kOpcodesAMD64 = { - kAsmOpcodeDecl("int", 0xCD) - kAsmOpcodeDecl("into", 0xCE) - kAsmOpcodeDecl("intd", 0xF1) - kAsmOpcodeDecl("int3", 0xC3) - kAsmOpcodeDecl("iret", 0xCF) - kAsmOpcodeDecl("retf", 0xCB) - kAsmOpcodeDecl("retn", 0xC3) - kAsmOpcodeDecl("ret", 0xC3) - kAsmOpcodeDecl("sti", 0xfb) - kAsmOpcodeDecl("cli", 0xfa) - kAsmOpcodeDecl("hlt", 0xf4) - kAsmOpcodeDecl("nop", 0x90) - kAsmOpcodeDecl("mov", 0x48) - kAsmOpcodeDecl("call", 0xFF) -}; - -#define kAsmRegisterLimit 15 diff --git a/NDKKit/AsmKit/CPU/amd64.hxx b/NDKKit/AsmKit/CPU/amd64.hxx new file mode 100644 index 0000000..f932c72 --- /dev/null +++ b/NDKKit/AsmKit/CPU/amd64.hxx @@ -0,0 +1,57 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +// @brief AMD64 support. +// @file CPU/amd64.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE) {.fName = __NAME, .fOpcode = __OPCODE}, + +typedef char i64_character_t; +typedef uint8_t i64_byte_t; +typedef uint16_t i64_hword_t; +typedef uint32_t i64_word_t; + +struct CpuOpcodeAMD64 +{ + std::string fName; + i64_byte_t fPrefixBytes[4]; + i64_hword_t fOpcode; + i64_hword_t fModReg; + i64_word_t fDisplacment; + i64_word_t fImmediate; +}; + +/// these two are edge cases +#define kAsmIntOpcode 0xCC +#define kasmIntOpcodeAlt 0xCD + +#define kAsmJumpOpcode 0x0F80 +#define kJumpLimit 30 +#define kJumpLimitStandard 0xE3 +#define kJumpLimitStandardLimit 0xEB + +inline std::vector kOpcodesAMD64 = { + kAsmOpcodeDecl("int", 0xCD) + kAsmOpcodeDecl("into", 0xCE) + kAsmOpcodeDecl("intd", 0xF1) + kAsmOpcodeDecl("int3", 0xC3) + kAsmOpcodeDecl("iret", 0xCF) + kAsmOpcodeDecl("retf", 0xCB) + kAsmOpcodeDecl("retn", 0xC3) + kAsmOpcodeDecl("ret", 0xC3) + kAsmOpcodeDecl("sti", 0xfb) + kAsmOpcodeDecl("cli", 0xfa) + kAsmOpcodeDecl("hlt", 0xf4) + kAsmOpcodeDecl("nop", 0x90) + kAsmOpcodeDecl("mov", 0x48) + kAsmOpcodeDecl("call", 0xFF) +}; + +#define kAsmRegisterLimit 15 diff --git a/NDKKit/AsmKit/CPU/arm64.hpp b/NDKKit/AsmKit/CPU/arm64.hpp deleted file mode 100644 index a63ddfb..0000000 --- a/NDKKit/AsmKit/CPU/arm64.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* ------------------------------------------- - -Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -/// @brief ARM64 encoding support. -/// @file CPU/arm64.hpp - -struct CpuOpcodeArm64; - -/// @brief ARM64 opcode header. -struct CpuOpcodeArm64 final -{ - uint8_t fOpcode; // opcode - uint8_t fRegisterLeft; // left register index - uint8_t fRegisterRight; // right register index - bool fRegisterLeftHooked; - bool fRegisterRightHooked; - uint32_t fImmediateValue; // immediate 32-bit value - bool fImmediateValueHooked; -}; diff --git a/NDKKit/AsmKit/CPU/arm64.hxx b/NDKKit/AsmKit/CPU/arm64.hxx new file mode 100644 index 0000000..09de3ee --- /dev/null +++ b/NDKKit/AsmKit/CPU/arm64.hxx @@ -0,0 +1,26 @@ +/* ------------------------------------------- + +Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief ARM64 encoding support. +/// @file CPU/arm64.hpp + +struct CpuOpcodeArm64; + +/// @brief ARM64 opcode header. +struct CpuOpcodeArm64 final +{ + uint8_t fOpcode; // opcode + uint8_t fRegisterLeft; // left register index + uint8_t fRegisterRight; // right register index + bool fRegisterLeftHooked; + bool fRegisterRightHooked; + uint32_t fImmediateValue; // immediate 32-bit value + bool fImmediateValueHooked; +}; diff --git a/NDKKit/AsmKit/CPU/ppc.hpp b/NDKKit/AsmKit/CPU/ppc.hpp deleted file mode 100644 index e3ea6c5..0000000 --- a/NDKKit/AsmKit/CPU/ppc.hpp +++ /dev/null @@ -1,1929 +0,0 @@ -/* ------------------------------------------- - - Some modifications are copyrighted under: - ZKA Technologies - - Original author: - Apple Inc - -------------------------------------------- */ - -#pragma once - -#include - -/// @note Based of: -/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html - -/* - * These defines are use in the cpus field of the instructions. If the field - * is zero it can execute on all cpus. The defines are or'ed together. This - * information is used to set the cpusubtype in the resulting object file. - */ -#define CPU601 0x1 -#define IMPL64 0x2 -#define OPTIONAL 0x4 -#define VMX 0x8 -#define CPU970 0x10 /* added to OPTIONAL insts that the 970 has */ -#define CPUMAHROUSS 0x12 /* optional mahrouss insts. */ - -enum optype -{ - NONE, /* no operand */ - JBSR, /* jbsr pseudo op */ - PCREL, /* PC relative (branch offset) */ - BADDR, /* Branch address (sign extended absolute address) */ - D, /* 16 bit displacement */ - DS, /* 14 bit displacement (double word) */ - SI, /* signed 16 bit immediate */ - UI, /* unsigned 16 bit immediate */ - HI, /* high 16 bit immediate (with truncation) */ - GREG, /* general register */ - G0REG, /* general register r1-r31 or 0 */ - FREG, /* float register */ - VREG, /* vector register */ - SGREG, /* segment register */ - SPREG, /* special register (or 10 bit number, 5 bit halves reversed) */ - BCND, /* branch condition opcode */ - CRF, /* condition register field */ - CRFONLY, /* condition register field only no expression allowed */ - sh, /* 6 bit number (0 - 63) (sh field, split and reversed) */ - mb, /* 6 bit number (0 - 63) (mb field, mb5 || mb0:4 reversed) */ - NUM, /* number */ - SNUM, /* signed number */ - NUM0, /* number (where 1< + +/// @note Based of: +/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html + +/* + * These defines are use in the cpus field of the instructions. If the field + * is zero it can execute on all cpus. The defines are or'ed together. This + * information is used to set the cpusubtype in the resulting object file. + */ +#define CPU601 0x1 +#define IMPL64 0x2 +#define OPTIONAL 0x4 +#define VMX 0x8 +#define CPU970 0x10 /* added to OPTIONAL insts that the 970 has */ +#define CPUMAHROUSS 0x12 /* optional mahrouss insts. */ + +enum optype +{ + NONE, /* no operand */ + JBSR, /* jbsr pseudo op */ + PCREL, /* PC relative (branch offset) */ + BADDR, /* Branch address (sign extended absolute address) */ + D, /* 16 bit displacement */ + DS, /* 14 bit displacement (double word) */ + SI, /* signed 16 bit immediate */ + UI, /* unsigned 16 bit immediate */ + HI, /* high 16 bit immediate (with truncation) */ + GREG, /* general register */ + G0REG, /* general register r1-r31 or 0 */ + FREG, /* float register */ + VREG, /* vector register */ + SGREG, /* segment register */ + SPREG, /* special register (or 10 bit number, 5 bit halves reversed) */ + BCND, /* branch condition opcode */ + CRF, /* condition register field */ + CRFONLY, /* condition register field only no expression allowed */ + sh, /* 6 bit number (0 - 63) (sh field, split and reversed) */ + mb, /* 6 bit number (0 - 63) (mb field, mb5 || mb0:4 reversed) */ + NUM, /* number */ + SNUM, /* signed number */ + NUM0, /* number (where 1< - -#define SizeType size_t - -#define VoidPtr void* -#define voidPtr VoidPtr - -#define UIntPtr uintptr_t - -#define Int64 int64_t -#define UInt64 uint64_t - -#define Int32 int -#define UInt32 unsigned - -#define Bool bool - -#define Int16 int16_t -#define UInt16 uint16_t - -#define Int8 int8_t -#define UInt8 uint8_t - -#define CharType char -#define Boolean bool - -#include -#include -#include - -#define nullPtr std::nullptr_t - -#define MUST_PASS(E) assert(E) - -#ifndef __FORCE_STRLEN -#define __FORCE_STRLEN 1 - -#define string_length(len) strlen(len) -#endif - -#ifndef __FORCE_MEMCPY -#define __FORCE_MEMCPY 1 - -#define rt_copy_memory(dst, src, len) memcpy(dst, src, len) -#endif - -#define MPCC_COPY_DELETE(KLASS) \ - KLASS& operator=(const KLASS&) = delete; \ - KLASS(const KLASS&) = delete; - -#define MPCC_COPY_DEFAULT(KLASS) \ - KLASS& operator=(const KLASS&) = default; \ - KLASS(const KLASS&) = default; - -#define MPCC_MOVE_DELETE(KLASS) \ - KLASS& operator=(KLASS&&) = delete; \ - KLASS(KLASS&&) = delete; - -#define MPCC_MOVE_DEFAULT(KLASS) \ - KLASS& operator=(KLASS&&) = default; \ - KLASS(KLASS&&) = default; - -#include -#include -#include -#include - -namespace CompilerKit -{ - inline constexpr int BASE_YEAR = 1900; - - inline std::string current_date() noexcept - { - auto time_data = time(nullptr); - auto time_struct = gmtime(&time_data); - - std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); - fmt += "-"; - fmt += std::to_string(time_struct->tm_mon + 1); - fmt += "-"; - fmt += std::to_string(time_struct->tm_mday); - - return fmt; - } - - inline bool to_str(CharType* str, Int32 limit, Int32 base) noexcept - { - if (limit == 0) - return false; - - Int32 copy_limit = limit; - Int32 cnt = 0; - Int32 ret = base; - - while (limit != 1) - { - ret = ret % 10; - str[cnt] = ret; - - ++cnt; - --limit; - --ret; - } - - str[copy_limit] = '\0'; - return true; - } -} // namespace CompilerKit - -#define PACKED __attribute__((packed)) - -typedef char char_type; - -#define kObjectFileExt ".obj" -#define kBinaryFileExt ".bin" - -#define kAsmFileExts \ - { \ - ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ - } - -#ifdef __NDK_MODULE__ -#define NDK_MODULE(name) int name(int argc, char** argv) -#else -#define NDK_MODULE(name) int main(int argc, char** argv) -#endif /* ifdef __NDK_MODULE__ */ - -#pragma scalar_storage_order big-endian - -#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/NDKKit/Defines.hxx b/NDKKit/Defines.hxx new file mode 100644 index 0000000..31c1998 --- /dev/null +++ b/NDKKit/Defines.hxx @@ -0,0 +1,147 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#ifndef __MPCC_DEFINES_HPP__ +#define __MPCC_DEFINES_HPP__ + +#ifndef Yes +#define Yes true +#endif // ifndef Yes + +#ifndef No +#define No false +#endif // ifndef No + +#include + +#define SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int +#define UInt32 unsigned + +#define Bool bool + +#define Int16 int16_t +#define UInt16 uint16_t + +#define Int8 int8_t +#define UInt8 uint8_t + +#define CharType char +#define Boolean bool + +#include +#include +#include + +#define nullPtr std::nullptr_t + +#define MUST_PASS(E) assert(E) + +#ifndef __FORCE_STRLEN +#define __FORCE_STRLEN 1 + +#define string_length(len) strlen(len) +#endif + +#ifndef __FORCE_MEMCPY +#define __FORCE_MEMCPY 1 + +#define rt_copy_memory(dst, src, len) memcpy(dst, src, len) +#endif + +#define MPCC_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define MPCC_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define MPCC_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define MPCC_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +#include +#include +#include +#include + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() noexcept + { + auto time_data = time(nullptr); + auto time_struct = gmtime(&time_data); + + std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mon + 1); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mday); + + return fmt; + } + + inline bool to_str(CharType* str, Int32 limit, Int32 base) noexcept + { + if (limit == 0) + return false; + + Int32 copy_limit = limit; + Int32 cnt = 0; + Int32 ret = base; + + while (limit != 1) + { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; + } +} // namespace CompilerKit + +#define PACKED __attribute__((packed)) + +typedef char char_type; + +#define kObjectFileExt ".obj" +#define kBinaryFileExt ".bin" + +#define kAsmFileExts \ + { \ + ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ + } + +#ifdef __NDK_MODULE__ +#define NDK_MODULE(name) int name(int argc, char** argv) +#else +#define NDK_MODULE(name) int main(int argc, char** argv) +#endif /* ifdef __NDK_MODULE__ */ + +#pragma scalar_storage_order big-endian + +#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/NDKKit/Macros.hpp b/NDKKit/Macros.hpp deleted file mode 100644 index c190cda..0000000 --- a/NDKKit/Macros.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -/// @brief provide support for Macros.hpp header. - -#ifndef _CK_CL_HPP -#define _CK_CL_HPP - -#define MPCC_COPY_DELETE(KLASS) \ - KLASS& operator=(const KLASS&) = delete; \ - KLASS(const KLASS&) = delete; - -#define MPCC_COPY_DEFAULT(KLASS) \ - KLASS& operator=(const KLASS&) = default; \ - KLASS(const KLASS&) = default; - -#define MPCC_MOVE_DELETE(KLASS) \ - KLASS& operator=(KLASS&&) = delete; \ - KLASS(KLASS&&) = delete; - -#define MPCC_MOVE_DEFAULT(KLASS) \ - KLASS& operator=(KLASS&&) = default; \ - KLASS(KLASS&&) = default; - -/// @note xxxx is the error placeholder, in hexadecimal. -#define MPCC_ERROR_PREFIX_CXX "CXXxxxx" -#define MPCC_ERROR_PREFIX_CL "CLxxxx" -#define MPCC_ERROR_PREFIX_ASM "ASMxxxx" - -#endif /* ifndef _CK_CL_HPP */ diff --git a/NDKKit/Macros.hxx b/NDKKit/Macros.hxx new file mode 100644 index 0000000..c190cda --- /dev/null +++ b/NDKKit/Macros.hxx @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +/// @brief provide support for Macros.hpp header. + +#ifndef _CK_CL_HPP +#define _CK_CL_HPP + +#define MPCC_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define MPCC_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define MPCC_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define MPCC_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +/// @note xxxx is the error placeholder, in hexadecimal. +#define MPCC_ERROR_PREFIX_CXX "CXXxxxx" +#define MPCC_ERROR_PREFIX_CL "CLxxxx" +#define MPCC_ERROR_PREFIX_ASM "ASMxxxx" + +#endif /* ifndef _CK_CL_HPP */ diff --git a/NDKKit/NFC/AE.hpp b/NDKKit/NFC/AE.hpp deleted file mode 100644 index 1c929f9..0000000 --- a/NDKKit/NFC/AE.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * ======================================================== - * - * NDK - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -#define kAEMag0 'A' -#define kAEMag1 'E' - -#define kAESymbolLen 64 -#define kAEPad 8 -#define kAEMagLen 2 -#define kAEInvalidOpcode 0x00 - -// Advanced Executable File Format for MetroLink. -// Reloctable by offset is the default strategy. -// You can also relocate at runtime but that's up to the operating system -// loader. - -namespace CompilerKit -{ - // @brief Advanced Executable Header - // One thing to keep in mind. - // This object format, is reloctable. - typedef struct AEHeader final - { - CharType fMagic[kAEMagLen]; - CharType fArch; - CharType fSubArch; - SizeType fCount; - CharType fSize; - SizeType fStartCode; - SizeType fCodeSize; - CharType fPad[kAEPad]; - } PACKED AEHeader, *AEHeaderPtr; - - // @brief Advanced Executable Record. - // Could be data, code or bss. - // fKind must be filled with PEF fields. - - typedef struct AERecordHeader final - { - CharType fName[kAESymbolLen]; - SizeType fKind; - SizeType fSize; - SizeType fFlags; - UIntPtr fOffset; - CharType fPad[kAEPad]; - } PACKED AERecordHeader, *AERecordHeaderPtr; - - enum - { - kKindRelocationByOffset = 0x23f, - kKindRelocationAtRuntime = 0x34f, - }; -} // namespace CompilerKit - -// provide operator<< for AE - -std::ofstream& operator<<(std::ofstream& fp, CompilerKit::AEHeader& container) -{ - fp.write((char*)&container, sizeof(CompilerKit::AEHeader)); - - return fp; -} - -std::ofstream& operator<<(std::ofstream& fp, - CompilerKit::AERecordHeader& container) -{ - fp.write((char*)&container, sizeof(CompilerKit::AERecordHeader)); - - return fp; -} - -std::ifstream& operator>>(std::ifstream& fp, CompilerKit::AEHeader& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::AEHeader)); - return fp; -} - -std::ifstream& operator>>(std::ifstream& fp, - CompilerKit::AERecordHeader& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::AERecordHeader)); - return fp; -} - -namespace CompilerKit::Utils -{ - /** - * @brief AE Reader protocol - * - */ - class AEReadableProtocol final - { - public: - std::ifstream FP; - - public: - explicit AEReadableProtocol() = default; - ~AEReadableProtocol() = default; - - MPCC_COPY_DELETE(AEReadableProtocol); - - /** - * @brief Read AE record - * - * @param raw the containing buffer - * @param sz it's size (without sizeof(AERecordHeader) added to it.) - * @return AERecordHeaderPtr - */ - AERecordHeaderPtr Read(char* raw, std::size_t sz) - { - if (!raw) - return nullptr; - - return this->_Read(raw, sz * sizeof(AERecordHeader)); - } - - private: - /** - * @brief Implementation of Read for raw classes. - * - * @tparam TypeClass The class to read. - * @param raw the buffer - * @param sz the size - * @return TypeClass* the returning class. - */ - template - TypeClass* _Read(char* raw, std::size_t sz) - { - FP.read(raw, std::streamsize(sz)); - return reinterpret_cast(raw); - } - }; -} // namespace CompilerKit::Utils diff --git a/NDKKit/NFC/AE.hxx b/NDKKit/NFC/AE.hxx new file mode 100644 index 0000000..22ad05b --- /dev/null +++ b/NDKKit/NFC/AE.hxx @@ -0,0 +1,143 @@ +/* + * ======================================================== + * + * NDK + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +#define kAEMag0 'A' +#define kAEMag1 'E' + +#define kAESymbolLen 64 +#define kAEPad 8 +#define kAEMagLen 2 +#define kAEInvalidOpcode 0x00 + +// Advanced Executable File Format for MetroLink. +// Reloctable by offset is the default strategy. +// You can also relocate at runtime but that's up to the operating system +// loader. + +namespace CompilerKit +{ + // @brief Advanced Executable Header + // One thing to keep in mind. + // This object format, is reloctable. + typedef struct AEHeader final + { + CharType fMagic[kAEMagLen]; + CharType fArch; + CharType fSubArch; + SizeType fCount; + CharType fSize; + SizeType fStartCode; + SizeType fCodeSize; + CharType fPad[kAEPad]; + } PACKED AEHeader, *AEHeaderPtr; + + // @brief Advanced Executable Record. + // Could be data, code or bss. + // fKind must be filled with PEF fields. + + typedef struct AERecordHeader final + { + CharType fName[kAESymbolLen]; + SizeType fKind; + SizeType fSize; + SizeType fFlags; + UIntPtr fOffset; + CharType fPad[kAEPad]; + } PACKED AERecordHeader, *AERecordHeaderPtr; + + enum + { + kKindRelocationByOffset = 0x23f, + kKindRelocationAtRuntime = 0x34f, + }; +} // namespace CompilerKit + +// provide operator<< for AE + +std::ofstream& operator<<(std::ofstream& fp, CompilerKit::AEHeader& container) +{ + fp.write((char*)&container, sizeof(CompilerKit::AEHeader)); + + return fp; +} + +std::ofstream& operator<<(std::ofstream& fp, + CompilerKit::AERecordHeader& container) +{ + fp.write((char*)&container, sizeof(CompilerKit::AERecordHeader)); + + return fp; +} + +std::ifstream& operator>>(std::ifstream& fp, CompilerKit::AEHeader& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::AEHeader)); + return fp; +} + +std::ifstream& operator>>(std::ifstream& fp, + CompilerKit::AERecordHeader& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::AERecordHeader)); + return fp; +} + +namespace CompilerKit::Utils +{ + /** + * @brief AE Reader protocol + * + */ + class AEReadableProtocol final + { + public: + std::ifstream FP; + + public: + explicit AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + MPCC_COPY_DELETE(AEReadableProtocol); + + /** + * @brief Read AE record + * + * @param raw the containing buffer + * @param sz it's size (without sizeof(AERecordHeader) added to it.) + * @return AERecordHeaderPtr + */ + AERecordHeaderPtr Read(char* raw, std::size_t sz) + { + if (!raw) + return nullptr; + + return this->_Read(raw, sz * sizeof(AERecordHeader)); + } + + private: + /** + * @brief Implementation of Read for raw classes. + * + * @tparam TypeClass The class to read. + * @param raw the buffer + * @param sz the size + * @return TypeClass* the returning class. + */ + template + TypeClass* _Read(char* raw, std::size_t sz) + { + FP.read(raw, std::streamsize(sz)); + return reinterpret_cast(raw); + } + }; +} // namespace CompilerKit::Utils diff --git a/NDKKit/NFC/ELF.hpp b/NDKKit/NFC/ELF.hpp deleted file mode 100644 index 4f0d0ae..0000000 --- a/NDKKit/NFC/ELF.hpp +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include -#include - -struct file; - -#ifndef elf_read_implies_exec -/* Executables for which elf_read_implies_exec() returns TRUE will - have the READ_IMPLIES_EXEC personality flag set automatically. - Override in asm/elf.h as needed. */ -#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 -#endif - -/* 32-bit ELF base types. */ -typedef uint32_t Elf32_Addr; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Word; - -/* 64-bit ELF base types. */ -typedef uintptr_t Elf64_Addr; -typedef uint16_t Elf64_Half; -typedef int16_t Elf64_SHalf; -typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Sword; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* These constants are for the segment types stored in the image headers */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 /* Thread local storage segment */ -#define PT_LOOS 0x60000000 /* OS-specific */ -#define PT_HIOS 0x6fffffff /* OS-specific */ -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff -#define PT_GNU_EH_FRAME 0x6474e550 - -#define PT_GNU_STACK (PT_LOOS + 0x474e551) - -/* These constants define the different elf file types */ -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - -/* This is the info that is needed to parse the dynamic section of the file */ -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_ENCODING 32 -#define OLD_DT_LOOS 0x60000000 -#define DT_LOOS 0x6000000d -#define DT_HIOS 0x6ffff000 -#define DT_VALRNGLO 0x6ffffd00 -#define DT_VALRNGHI 0x6ffffdff -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_VERSYM 0x6ffffff0 -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa -#define DT_FLAGS_1 0x6ffffffb -#define DT_VERDEF 0x6ffffffc -#define DT_VERDEFNUM 0x6ffffffd -#define DT_VERNEED 0x6ffffffe -#define DT_VERNEEDNUM 0x6fffffff -#define OLD_DT_HIOS 0x6fffffff -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - -/* This info is needed when parsing the symbol table */ -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 - -#define ELF_ST_BIND(x) ((x) >> 4) -#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) -#define ELF32_ST_BIND(x) ELF_ST_BIND(x) -#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) -#define ELF64_ST_BIND(x) ELF_ST_BIND(x) -#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) - -typedef struct dynamic -{ - Elf32_Sword d_tag; - union { - Elf32_Sword d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -typedef struct -{ - Elf64_Sxword d_tag; /* entry tag value */ - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - -/* The following are used with relocations */ -#define ELF32_R_SYM(x) ((x) >> 8) -#define ELF32_R_TYPE(x) ((x)&0xff) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i)&0xffffffff) - -typedef struct elf32_rel -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct elf64_rel -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ -} Elf64_Rel; - -typedef struct elf32_rela -{ - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct elf64_rela -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ - Elf64_Sxword r_addend; /* Constant addend used to compute value */ -} Elf64_Rela; - -typedef struct elf32_sym -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -typedef struct elf64_sym -{ - Elf64_Word st_name; /* Symbol name, index in string tbl */ - unsigned char st_info; /* Type and binding attributes */ - unsigned char st_other; /* No defined meaning, 0 */ - Elf64_Half st_shndx; /* Associated section index */ - Elf64_Addr st_value; /* Value of the symbol */ - Elf64_Xword st_size; /* Associated symbol size */ -} Elf64_Sym; - -#define EI_NIDENT 16 - -typedef struct elf32_hdr -{ - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point */ - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64_hdr -{ - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -/* These constants define the permissions on sections in the program - header, p_flags. */ -#define PF_R 0x4 -#define PF_W 0x2 -#define PF_X 0x1 - -typedef struct elf32_phdr -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct elf64_phdr -{ - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment, file & memory */ -} Elf64_Phdr; - -/* sh_type */ -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_NUM 12 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -/* sh_flags */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 - -/* special section indexes */ -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct elf64_shdr -{ - Elf64_Word sh_name; /* Section name, index in string tbl */ - Elf64_Word sh_type; /* Type of section */ - Elf64_Xword sh_flags; /* Miscellaneous section attributes */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Size of section in bytes */ - Elf64_Word sh_link; /* Index of another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -#define EI_MAG0 0 /* e_ident[] indexes */ -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_PAD 8 - -#define ELFMAG0 0x7f /* EI_MAG */ -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define ELFCLASSNONE 0 /* EI_CLASS */ -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define ELFCLASSNUM 3 - -#define ELFDATANONE 0 /* e_ident[EI_DATA] */ -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define EV_NONE 0 /* e_version, EI_VERSION */ -#define EV_CURRENT 1 -#define EV_NUM 2 - -#define ELFOSABI_NONE 0 -#define ELFOSABI_LINUX 3 - -#ifndef ELF_OSABI -#define ELF_OSABI ELFOSABI_NONE -#endif - -/* Notes used in ET_CORE */ -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ -#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ -#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ -#define NT_PPC_VSX 0x102 /* POWER VSX registers */ -#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ -#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ -#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ - -/* Note header in a PT_NOTE section */ -typedef struct elf32_note -{ - Elf32_Word n_namesz; /* Name size */ - Elf32_Word n_descsz; /* Content size */ - Elf32_Word n_type; /* Content type */ -} Elf32_Nhdr; - -/* Note header in a PT_NOTE section */ -typedef struct elf64_note -{ - Elf64_Word n_namesz; /* Name size */ - Elf64_Word n_descsz; /* Content size */ - Elf64_Word n_type; /* Content type */ -} Elf64_Nhdr; diff --git a/NDKKit/NFC/ELF.hxx b/NDKKit/NFC/ELF.hxx new file mode 100644 index 0000000..4f0d0ae --- /dev/null +++ b/NDKKit/NFC/ELF.hxx @@ -0,0 +1,389 @@ +#pragma once + +#include +#include + +struct file; + +#ifndef elf_read_implies_exec +/* Executables for which elf_read_implies_exec() returns TRUE will + have the READ_IMPLIES_EXEC personality flag set automatically. + Override in asm/elf.h as needed. */ +#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 +#endif + +/* 32-bit ELF base types. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit ELF base types. */ +typedef uintptr_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 + +#define PT_GNU_STACK (PT_LOOS + 0x474e551) + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct dynamic +{ + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x)&0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) + +typedef struct elf32_rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym +{ + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr +{ + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr +{ + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* POWER VSX registers */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ + +/* Note header in a PT_NOTE section */ +typedef struct elf32_note +{ + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* Note header in a PT_NOTE section */ +typedef struct elf64_note +{ + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; diff --git a/NDKKit/NFC/ErrorID.hpp b/NDKKit/NFC/ErrorID.hpp deleted file mode 100644 index c45b4b0..0000000 --- a/NDKKit/NFC/ErrorID.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -#define MPCC_EXEC_ERROR -30 -#define MPCC_FILE_NOT_FOUND -31 -#define MPCC_DIR_NOT_FOUND -32 -#define MPCC_FILE_EXISTS -33 -#define MPCC_TOO_LONG -34 -#define MPCC_INVALID_DATA -35 -#define MPCC_UNIMPLEMENTED -36 -#define MPCC_FAT_ERROR -37 diff --git a/NDKKit/NFC/ErrorID.hxx b/NDKKit/NFC/ErrorID.hxx new file mode 100644 index 0000000..9845a8b --- /dev/null +++ b/NDKKit/NFC/ErrorID.hxx @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +#define MPCC_EXEC_ERROR -30 +#define MPCC_FILE_NOT_FOUND -31 +#define MPCC_DIR_NOT_FOUND -32 +#define MPCC_FILE_EXISTS -33 +#define MPCC_TOO_LONG -34 +#define MPCC_INVALID_DATA -35 +#define MPCC_UNIMPLEMENTED -36 +#define MPCC_FAT_ERROR -37 diff --git a/NDKKit/NFC/ErrorOr.hpp b/NDKKit/NFC/ErrorOr.hpp deleted file mode 100644 index ed134a7..0000000 --- a/NDKKit/NFC/ErrorOr.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - using ErrorT = UInt32; - - template - class ErrorOr final - { - public: - ErrorOr() = default; - ~ErrorOr() = default; - - public: - explicit ErrorOr(Int32 err) - : mId(err) - { - } - - explicit ErrorOr(nullPtr Null) - { - } - - explicit ErrorOr(T Class) - : mRef(Class) - { - } - - ErrorOr& operator=(const ErrorOr&) = default; - ErrorOr(const ErrorOr&) = default; - - Ref Leak() - { - return mRef; - } - - operator bool() - { - return mRef; - } - - private: - Ref mRef; - Int32 mId{0}; - }; - - using ErrorOrAny = ErrorOr; - -} // namespace CompilerKit diff --git a/NDKKit/NFC/ErrorOr.hxx b/NDKKit/NFC/ErrorOr.hxx new file mode 100644 index 0000000..936654a --- /dev/null +++ b/NDKKit/NFC/ErrorOr.hxx @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + using ErrorT = UInt32; + + template + class ErrorOr final + { + public: + ErrorOr() = default; + ~ErrorOr() = default; + + public: + explicit ErrorOr(Int32 err) + : mId(err) + { + } + + explicit ErrorOr(nullPtr Null) + { + } + + explicit ErrorOr(T Class) + : mRef(Class) + { + } + + ErrorOr& operator=(const ErrorOr&) = default; + ErrorOr(const ErrorOr&) = default; + + Ref Leak() + { + return mRef; + } + + operator bool() + { + return mRef; + } + + private: + Ref mRef; + Int32 mId{0}; + }; + + using ErrorOrAny = ErrorOr; + +} // namespace CompilerKit diff --git a/NDKKit/NFC/PEF.hpp b/NDKKit/NFC/PEF.hpp deleted file mode 100644 index 2f460b7..0000000 --- a/NDKKit/NFC/PEF.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -// @file PEF.hpp -// @brief Preferred Executable Format - -#define kPefMagic "Joy!" -#define kPefMagicFat "yoJ!" - -#define kPefExt ".exec" -#define kPefDylibExt ".lib" -#define kPefLibExt ".slib" -#define kPefObjectExt ".obj" -#define kPefDebugExt ".dbg" - -#define kPefMagicLen 5 - -#define kPefVersion 2 -#define kPefNameLen 255 - -#define kPefBaseOrigin (0x1000000) - -#define kPefStart "__ImageStart" - -namespace CompilerKit -{ - enum - { - kPefArchStart = 99, - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* 64x0 RISC architecture. */ - kPefArch32000, - kPefArchPowerPC, /* 64-bit POWER architecture. */ - kPefArchARM64, - kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefSubArchAMD, - kPefSubArchIntel, - kPefSubArchGeneric, - kPefSubArchIBM, - }; - - enum - { - kPefKindExec = 1, /* .exe */ - kPefKindSharedObject = 2, /* .lib */ - kPefKindObject = 4, /* .obj */ - kPefKindDebug = 5, /* .dbg */ - kPefKindDriver = 6, - kPefKindCount, - }; - - /* PEF container */ - typedef struct PEFContainer final - { - CharType Magic[kPefMagicLen]; - UInt32 Linker; - UInt32 Version; - UInt32 Kind; - UInt32 Abi; - UInt32 Cpu; - UInt32 SubCpu; /* Cpu specific information */ - UIntPtr Start; /* Origin of code */ - SizeType HdrSz; /* Size of header */ - SizeType Count; /* container header count */ - } PACKED PEFContainer; - - /* First PEFCommandHeader starts after PEFContainer */ - /* Last container is __exec_end */ - - /* PEF executable section and commands. */ - - typedef struct PEFCommandHeader final - { - CharType Name[kPefNameLen]; /* container name */ - UInt32 Cpu; /* container cpu */ - UInt32 SubCpu; /* container sub-cpu */ - UInt32 Flags; /* container flags */ - UInt16 Kind; /* container kind */ - UIntPtr Offset; /* file offset */ - SizeType Size; /* file size */ - } PACKED PEFCommandHeader; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - kPefCount = 4, - kPefInvalid = 0xFF, - }; -} // namespace CompilerKit - -inline std::ofstream& operator<<(std::ofstream& fp, - CompilerKit::PEFContainer& container) -{ - fp.write((char*)&container, sizeof(CompilerKit::PEFContainer)); - return fp; -} - -inline std::ofstream& operator<<(std::ofstream& fp, - CompilerKit::PEFCommandHeader& container) -{ - fp.write((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); - return fp; -} - -std::ifstream& operator>>(std::ifstream& fp, - CompilerKit::PEFContainer& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::PEFContainer)); - return fp; -} - -std::ifstream& operator>>(std::ifstream& fp, - CompilerKit::PEFCommandHeader& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); - return fp; -} diff --git a/NDKKit/NFC/PEF.hxx b/NDKKit/NFC/PEF.hxx new file mode 100644 index 0000000..f1cd8ec --- /dev/null +++ b/NDKKit/NFC/PEF.hxx @@ -0,0 +1,134 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +// @file PEF.hpp +// @brief Preferred Executable Format + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefExt ".exec" +#define kPefDylibExt ".lib" +#define kPefLibExt ".slib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" + +#define kPefMagicLen 5 + +#define kPefVersion 2 +#define kPefNameLen 255 + +#define kPefBaseOrigin (0x1000000) + +#define kPefStart "__ImageStart" + +namespace CompilerKit +{ + enum + { + kPefArchStart = 99, + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* 64x0 RISC architecture. */ + kPefArch32000, + kPefArchPowerPC, /* 64-bit POWER architecture. */ + kPefArchARM64, + kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefSubArchAMD, + kPefSubArchIntel, + kPefSubArchGeneric, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .exe */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDebug = 5, /* .dbg */ + kPefKindDriver = 6, + kPefKindCount, + }; + + /* PEF container */ + typedef struct PEFContainer final + { + CharType Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; /* Origin of code */ + SizeType HdrSz; /* Size of header */ + SizeType Count; /* container header count */ + } PACKED PEFContainer; + + /* First PEFCommandHeader starts after PEFContainer */ + /* Last container is __exec_end */ + + /* PEF executable section and commands. */ + + typedef struct PEFCommandHeader final + { + CharType Name[kPefNameLen]; /* container name */ + UInt32 Cpu; /* container cpu */ + UInt32 SubCpu; /* container sub-cpu */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* file offset */ + SizeType Size; /* file size */ + } PACKED PEFCommandHeader; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + kPefCount = 4, + kPefInvalid = 0xFF, + }; +} // namespace CompilerKit + +inline std::ofstream& operator<<(std::ofstream& fp, + CompilerKit::PEFContainer& container) +{ + fp.write((char*)&container, sizeof(CompilerKit::PEFContainer)); + return fp; +} + +inline std::ofstream& operator<<(std::ofstream& fp, + CompilerKit::PEFCommandHeader& container) +{ + fp.write((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); + return fp; +} + +std::ifstream& operator>>(std::ifstream& fp, + CompilerKit::PEFContainer& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::PEFContainer)); + return fp; +} + +std::ifstream& operator>>(std::ifstream& fp, + CompilerKit::PEFCommandHeader& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); + return fp; +} diff --git a/NDKKit/NFC/Ref.hpp b/NDKKit/NFC/Ref.hpp deleted file mode 100644 index 0f9c0e3..0000000 --- a/NDKKit/NFC/Ref.hpp +++ /dev/null @@ -1,97 +0,0 @@ - -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -namespace CompilerKit -{ - // @author Amlal - // @brief Reference holder class, refers to a pointer of data in static memory. - template - class Ref final - { - public: - explicit Ref() = default; - - ~Ref() - { - if (m_Strong) - { - (*m_Class).~T(); - } - } - - public: - explicit Ref(T cls, const bool& strong = false) - : m_Class(&cls), m_Strong(strong) - { - } - - Ref& operator=(T ref) - { - m_Class = ref; - return *this; - } - - public: - T operator->() const - { - return m_Class; - } - - T& Leak() - { - return *m_Class; - } - - T operator*() - { - return *m_Class; - } - - bool IsStrong() const - { - return m_Strong; - } - - operator bool() - { - return *m_Class; - } - - private: - T* m_Class; - bool m_Strong{false}; - }; - - template - class NonNullRef final - { - public: - explicit NonNullRef() = delete; - - explicit NonNullRef(T* ref) - : m_Ref(ref, true) - { - } - - Ref& operator->() - { - MUST_PASS(m_Ref); - return m_Ref; - } - - NonNullRef& operator=(const NonNullRef& ref) = delete; - NonNullRef(const NonNullRef& ref) = default; - - private: - Ref m_Ref{nullptr}; - }; -} // namespace CompilerKit diff --git a/NDKKit/NFC/Ref.hxx b/NDKKit/NFC/Ref.hxx new file mode 100644 index 0000000..0f9c0e3 --- /dev/null +++ b/NDKKit/NFC/Ref.hxx @@ -0,0 +1,97 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +namespace CompilerKit +{ + // @author Amlal + // @brief Reference holder class, refers to a pointer of data in static memory. + template + class Ref final + { + public: + explicit Ref() = default; + + ~Ref() + { + if (m_Strong) + { + (*m_Class).~T(); + } + } + + public: + explicit Ref(T cls, const bool& strong = false) + : m_Class(&cls), m_Strong(strong) + { + } + + Ref& operator=(T ref) + { + m_Class = ref; + return *this; + } + + public: + T operator->() const + { + return m_Class; + } + + T& Leak() + { + return *m_Class; + } + + T operator*() + { + return *m_Class; + } + + bool IsStrong() const + { + return m_Strong; + } + + operator bool() + { + return *m_Class; + } + + private: + T* m_Class; + bool m_Strong{false}; + }; + + template + class NonNullRef final + { + public: + explicit NonNullRef() = delete; + + explicit NonNullRef(T* ref) + : m_Ref(ref, true) + { + } + + Ref& operator->() + { + MUST_PASS(m_Ref); + return m_Ref; + } + + NonNullRef& operator=(const NonNullRef& ref) = delete; + NonNullRef(const NonNullRef& ref) = default; + + private: + Ref m_Ref{nullptr}; + }; +} // namespace CompilerKit diff --git a/NDKKit/NFC/String.hpp b/NDKKit/NFC/String.hpp deleted file mode 100644 index 200bf2c..0000000 --- a/NDKKit/NFC/String.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - /** - * @brief StringView class, contains a C string and manages it. - * @note No need to manage it it's getting deleted by default. - */ - - class StringView final - { - public: - explicit StringView() = delete; - - explicit StringView(SizeType Sz) noexcept - : m_Sz(Sz) - { - m_Data = new char[Sz]; - assert(m_Data); - } - - ~StringView() noexcept - { - if (m_Data) - { - memset(m_Data, 0, m_Sz); - delete[] m_Data; - - m_Data = nullptr; - } - } - - MPCC_COPY_DEFAULT(StringView); - - CharType* Data(); - const CharType* CData() const; - SizeType Length() const; - - bool operator==(const CharType* rhs) const; - bool operator!=(const CharType* rhs) const; - - bool operator==(const StringView& rhs) const; - bool operator!=(const StringView& rhs) const; - - StringView& operator+=(const CharType* rhs); - StringView& operator+=(const StringView& rhs); - - operator bool() - { - return m_Data && m_Data[0] != 0; - } - - bool operator!() - { - return !m_Data || m_Data[0] == 0; - } - - private: - char* m_Data{nullptr}; - SizeType m_Sz{0}; - SizeType m_Cur{0}; - - friend class StringBuilder; - }; - - /** - * @brief StringBuilder class - * @note These results shall call delete[] after they're used. - */ - struct StringBuilder final - { - static StringView Construct(const CharType* data); - static const char* FromInt(const char* fmt, int n); - static const char* FromBool(const char* fmt, bool n); - static const char* Format(const char* fmt, const char* from); - static bool Equals(const char* lhs, const char* rhs); - }; -} // namespace CompilerKit diff --git a/NDKKit/NFC/String.hxx b/NDKKit/NFC/String.hxx new file mode 100644 index 0000000..395fe67 --- /dev/null +++ b/NDKKit/NFC/String.hxx @@ -0,0 +1,90 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + /** + * @brief StringView class, contains a C string and manages it. + * @note No need to manage it it's getting deleted by default. + */ + + class StringView final + { + public: + explicit StringView() = delete; + + explicit StringView(SizeType Sz) noexcept + : m_Sz(Sz) + { + m_Data = new char[Sz]; + assert(m_Data); + } + + ~StringView() noexcept + { + if (m_Data) + { + memset(m_Data, 0, m_Sz); + delete[] m_Data; + + m_Data = nullptr; + } + } + + MPCC_COPY_DEFAULT(StringView); + + CharType* Data(); + const CharType* CData() const; + SizeType Length() const; + + bool operator==(const CharType* rhs) const; + bool operator!=(const CharType* rhs) const; + + bool operator==(const StringView& rhs) const; + bool operator!=(const StringView& rhs) const; + + StringView& operator+=(const CharType* rhs); + StringView& operator+=(const StringView& rhs); + + operator bool() + { + return m_Data && m_Data[0] != 0; + } + + bool operator!() + { + return !m_Data || m_Data[0] == 0; + } + + private: + char* m_Data{nullptr}; + SizeType m_Sz{0}; + SizeType m_Cur{0}; + + friend class StringBuilder; + }; + + /** + * @brief StringBuilder class + * @note These results shall call delete[] after they're used. + */ + struct StringBuilder final + { + static StringView Construct(const CharType* data); + static const char* FromInt(const char* fmt, int n); + static const char* FromBool(const char* fmt, bool n); + static const char* Format(const char* fmt, const char* from); + static bool Equals(const char* lhs, const char* rhs); + }; +} // namespace CompilerKit diff --git a/NDKKit/NFC/XCOFF.hxx b/NDKKit/NFC/XCOFF.hxx index 57ecfd2..97d3ab6 100644 --- a/NDKKit/NFC/XCOFF.hxx +++ b/NDKKit/NFC/XCOFF.hxx @@ -14,7 +14,7 @@ #ifndef __XCOFF__ #define __XCOFF__ -#include +#include #define kXCOFF64Magic 0x01F7 diff --git a/NDKKit/Parser.hpp b/NDKKit/Parser.hpp deleted file mode 100644 index c67057d..0000000 --- a/NDKKit/Parser.hpp +++ /dev/null @@ -1,178 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - inline auto cInvalidLang = "?"; - - /// @brief Compiler backend, implements a frontend, such as C, C++... - /// See Toolchain, for some examples. - class CompilerBackend - { - public: - explicit CompilerBackend() = default; - virtual ~CompilerBackend() = default; - - MPCC_COPY_DEFAULT(CompilerBackend); - - // NOTE: cast this to your user defined ast. - typedef void* AstType; - - //! @brief Compile a syntax tree ouf of the text. - //! Also takes the source file name for metadata. - - virtual bool Compile(const std::string& text, const char* file) = 0; - - //! @brief What language are we dealing with? - virtual const char* Language() - { - return cInvalidLang; - } - - virtual bool IsValid() - { - return strcmp(this->Language(), cInvalidLang); - } - }; - - struct SyntaxLeafList; - struct SyntaxLeafList; - struct CompilerKeyword; - - /// we want to do that because to separate keywords. - enum KeywordKind - { - eKeywordKindNamespace, - eKeywordKindFunctionStart, - eKeywordKindFunctionEnd, - eKeywordKindVariable, - eKeywordKindVariablePtr, - eKeywordKindType, - eKeywordKindTypePtr, - eKeywordKindExpressionBegin, - eKeywordKindExpressionEnd, - eKeywordKindArgSeparator, - eKeywordKindBodyStart, - eKeywordKindBodyEnd, - eKeywordKindClass, - eKeywordKindPtrAccess, - eKeywordKindAccess, - eKeywordKindIf, - eKeywordKindElse, - eKeywordKindElseIf, - eKeywordKindVariableAssign, - eKeywordKindVariableDec, - eKeywordKindVariableInc, - eKeywordKindConstant, - eKeywordKindTypedef, - eKeywordKindEndInstr, - eKeywordKindSpecifier, - eKeywordKindInvalid, - eKeywordKindReturn, - eKeywordKindCommentInline, - eKeywordKindCommentMultiLineStart, - eKeywordKindCommentMultiLineEnd, - eKeywordKindEq, - eKeywordKindNotEq, - eKeywordKindGreaterEq, - eKeywordKindLessEq, - eKeywordKindPtr, - }; - - /// \brief Compiler keyword information struct. - struct CompilerKeyword - { - std::string keyword_name; - KeywordKind keyword_kind = eKeywordKindInvalid; - }; - struct SyntaxLeafList final - { - struct SyntaxLeaf final - { - Int32 fUserType; -#ifdef __PK_USE_STRUCT_INSTEAD__ - CompilerKeyword fUserData; -#else - std::string fUserData; -#endif - - std::string fUserValue; - struct SyntaxLeaf* fNext; - }; - - std::vector fLeafList; - SizeType fNumLeafs; - - size_t SizeOf() - { - return fNumLeafs; - } - std::vector& Get() - { - return fLeafList; - } - SyntaxLeaf& At(size_t index) - { - return fLeafList[index]; - } - }; - - /// find the perfect matching word in a haystack. - /// \param haystack base string - /// \param needle the string we search for. - /// \return if we found it or not. - inline bool find_word(const std::string& haystack, - const std::string& needle) noexcept - { - auto index = haystack.find(needle); - - // check for needle validity. - if (index == std::string::npos) - return false; - - // declare lambda - auto not_part_of_word = [&](int index) { - if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) - return true; - - if (index < 0 || index >= haystack.size()) - return true; - - return false; - }; - - return not_part_of_word(index - 1) && not_part_of_word(index + needle.size()); - } - - /// find a word within strict conditions and returns a range of it. - /// \param haystack - /// \param needle - /// \return position of needle. - inline std::size_t find_word_range(const std::string& haystack, - const std::string& needle) noexcept - { - auto index = haystack.find(needle); - - // check for needle validity. - if (index == std::string::npos) - return false; - - if (!isalnum((haystack[index + needle.size() + 1])) && - !isdigit(haystack[index + needle.size() + 1]) && - !isalnum((haystack[index - needle.size() - 1])) && - !isdigit(haystack[index - needle.size() - 1])) - { - return index; - } - - return false; - } -} // namespace CompilerKit diff --git a/NDKKit/Parser.hxx b/NDKKit/Parser.hxx new file mode 100644 index 0000000..43ecc4a --- /dev/null +++ b/NDKKit/Parser.hxx @@ -0,0 +1,178 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + inline auto cInvalidLang = "?"; + + /// @brief Compiler backend, implements a frontend, such as C, C++... + /// See Toolchain, for some examples. + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + MPCC_COPY_DEFAULT(CompilerBackend); + + // NOTE: cast this to your user defined ast. + typedef void* AstType; + + //! @brief Compile a syntax tree ouf of the text. + //! Also takes the source file name for metadata. + + virtual bool Compile(const std::string& text, const char* file) = 0; + + //! @brief What language are we dealing with? + virtual const char* Language() + { + return cInvalidLang; + } + + virtual bool IsValid() + { + return strcmp(this->Language(), cInvalidLang); + } + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + struct CompilerKeyword; + + /// we want to do that because to separate keywords. + enum KeywordKind + { + eKeywordKindNamespace, + eKeywordKindFunctionStart, + eKeywordKindFunctionEnd, + eKeywordKindVariable, + eKeywordKindVariablePtr, + eKeywordKindType, + eKeywordKindTypePtr, + eKeywordKindExpressionBegin, + eKeywordKindExpressionEnd, + eKeywordKindArgSeparator, + eKeywordKindBodyStart, + eKeywordKindBodyEnd, + eKeywordKindClass, + eKeywordKindPtrAccess, + eKeywordKindAccess, + eKeywordKindIf, + eKeywordKindElse, + eKeywordKindElseIf, + eKeywordKindVariableAssign, + eKeywordKindVariableDec, + eKeywordKindVariableInc, + eKeywordKindConstant, + eKeywordKindTypedef, + eKeywordKindEndInstr, + eKeywordKindSpecifier, + eKeywordKindInvalid, + eKeywordKindReturn, + eKeywordKindCommentInline, + eKeywordKindCommentMultiLineStart, + eKeywordKindCommentMultiLineEnd, + eKeywordKindEq, + eKeywordKindNotEq, + eKeywordKindGreaterEq, + eKeywordKindLessEq, + eKeywordKindPtr, + }; + + /// \brief Compiler keyword information struct. + struct CompilerKeyword + { + std::string keyword_name; + KeywordKind keyword_kind = eKeywordKindInvalid; + }; + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; +#ifdef __PK_USE_STRUCT_INSTEAD__ + CompilerKeyword fUserData; +#else + std::string fUserData; +#endif + + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() + { + return fNumLeafs; + } + std::vector& Get() + { + return fLeafList; + } + SyntaxLeaf& At(size_t index) + { + return fLeafList[index]; + } + }; + + /// find the perfect matching word in a haystack. + /// \param haystack base string + /// \param needle the string we search for. + /// \return if we found it or not. + inline bool find_word(const std::string& haystack, + const std::string& needle) noexcept + { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) + return false; + + // declare lambda + auto not_part_of_word = [&](int index) { + if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) + return true; + + if (index < 0 || index >= haystack.size()) + return true; + + return false; + }; + + return not_part_of_word(index - 1) && not_part_of_word(index + needle.size()); + } + + /// find a word within strict conditions and returns a range of it. + /// \param haystack + /// \param needle + /// \return position of needle. + inline std::size_t find_word_range(const std::string& haystack, + const std::string& needle) noexcept + { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) + return false; + + if (!isalnum((haystack[index + needle.size() + 1])) && + !isdigit(haystack[index + needle.size() + 1]) && + !isalnum((haystack[index - needle.size() - 1])) && + !isdigit(haystack[index - needle.size() - 1])) + { + return index; + } + + return false; + } +} // namespace CompilerKit diff --git a/NDKKit/Sources/32asm.cxx b/NDKKit/Sources/32asm.cxx index 23111bc..4425e08 100644 --- a/NDKKit/Sources/32asm.cxx +++ b/NDKKit/Sources/32asm.cxx @@ -19,10 +19,10 @@ #define __ASM_NEED_32x0__ 1 -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/64asm.cxx b/NDKKit/Sources/64asm.cxx index 0a92157..4e084e7 100644 --- a/NDKKit/Sources/64asm.cxx +++ b/NDKKit/Sources/64asm.cxx @@ -19,10 +19,10 @@ #define __ASM_NEED_64x0__ 1 -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/64x0-cc.cxx b/NDKKit/Sources/64x0-cc.cxx index 19d995d..f38bb28 100644 --- a/NDKKit/Sources/64x0-cc.cxx +++ b/NDKKit/Sources/64x0-cc.cxx @@ -10,9 +10,9 @@ /// BUGS: 0 /// TODO: none -#include -#include -#include +#include +#include +#include #include #include #include @@ -1509,7 +1509,7 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// -#include +#include #define kPrintF printf #define kSplashCxx() \ diff --git a/NDKKit/Sources/AssemblyFactory.cxx b/NDKKit/Sources/AssemblyFactory.cxx index 9f1b768..a04f4fc 100644 --- a/NDKKit/Sources/AssemblyFactory.cxx +++ b/NDKKit/Sources/AssemblyFactory.cxx @@ -4,8 +4,8 @@ ------------------------------------------- */ -#include -#include +#include +#include /** * @file AssemblyFactory.cxx diff --git a/NDKKit/Sources/Detail/asmutils.hxx b/NDKKit/Sources/Detail/asmutils.hxx index abb7f82..d65c991 100644 --- a/NDKKit/Sources/Detail/asmutils.hxx +++ b/NDKKit/Sources/Detail/asmutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include using namespace CompilerKit; diff --git a/NDKKit/Sources/Detail/compilerutils.hxx b/NDKKit/Sources/Detail/compilerutils.hxx index fd2b6d2..c4674e8 100644 --- a/NDKKit/Sources/Detail/compilerutils.hxx +++ b/NDKKit/Sources/Detail/compilerutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include #define kZero64Section ".zero64" #define kCode64Section ".code64" diff --git a/NDKKit/Sources/String.cxx b/NDKKit/Sources/String.cxx index f69f9b9..87f4721 100644 --- a/NDKKit/Sources/String.cxx +++ b/NDKKit/Sources/String.cxx @@ -18,7 +18,7 @@ * */ -#include +#include namespace CompilerKit { CharType *StringView::Data() { return m_Data; } diff --git a/NDKKit/Sources/bpp.cxx b/NDKKit/Sources/bpp.cxx index 9a2943c..6c8ab95 100644 --- a/NDKKit/Sources/bpp.cxx +++ b/NDKKit/Sources/bpp.cxx @@ -9,8 +9,8 @@ /// BUGS: 0 -#include -#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/coff2ae.cxx b/NDKKit/Sources/coff2ae.cxx index c9ea8c0..eb2e133 100644 --- a/NDKKit/Sources/coff2ae.cxx +++ b/NDKKit/Sources/coff2ae.cxx @@ -4,9 +4,9 @@ ------------------------------------------- */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/cplusplus.cxx b/NDKKit/Sources/cplusplus.cxx index ae4a300..b8c73df 100644 --- a/NDKKit/Sources/cplusplus.cxx +++ b/NDKKit/Sources/cplusplus.cxx @@ -20,9 +20,9 @@ // import, @MLAutoRelease { ... }, fn foo() -> auto { ... } -#include -#include -#include +#include +#include +#include #include #include diff --git a/NDKKit/Sources/elf2ae.cxx b/NDKKit/Sources/elf2ae.cxx index 451c706..eb5169e 100644 --- a/NDKKit/Sources/elf2ae.cxx +++ b/NDKKit/Sources/elf2ae.cxx @@ -4,9 +4,9 @@ ------------------------------------------- */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/i64asm.cxx b/NDKKit/Sources/i64asm.cxx index ed77988..c2ce4ac 100644 --- a/NDKKit/Sources/i64asm.cxx +++ b/NDKKit/Sources/i64asm.cxx @@ -27,10 +27,10 @@ #define kAssemblerPragmaSymStr "#" #define kAssemblerPragmaSym '#' -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/link.cxx b/NDKKit/Sources/link.cxx index 0708bd0..db28a32 100644 --- a/NDKKit/Sources/link.cxx +++ b/NDKKit/Sources/link.cxx @@ -13,23 +13,23 @@ /// @note Do not look up for anything with .code64/.data64/.zero64! /// It will be loaded when program will start up! -#include +#include //! Assembler Kit -#include +#include //! Preferred Executable Format -#include -#include +#include +#include #include #include #include //! Dist version -#include +#include //! Advanced Executable Object Format -#include +#include //! C++ I/O headers. #include @@ -515,7 +515,7 @@ NDK_MODULE(NewOSLinker) std::string timeStampStr = "Container:BuildEpoch:"; timeStampStr += std::to_string(timestamp); - strcpy(dateHeader.Name, timeStampStr.c_str()); + strncpy(dateHeader.Name, timeStampStr.c_str(), timeStampStr.size()); dateHeader.Flags = 0; dateHeader.Kind = CompilerKit::kPefZero; diff --git a/NDKKit/Sources/power-as.cxx b/NDKKit/Sources/power-as.cxx index 8a6b7ef..81cfc15 100644 --- a/NDKKit/Sources/power-as.cxx +++ b/NDKKit/Sources/power-as.cxx @@ -17,12 +17,12 @@ #define __ASM_NEED_PPC__ 1 -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/NDKKit/Sources/power-cc.cxx b/NDKKit/Sources/power-cc.cxx index 4c07a04..deddcfd 100644 --- a/NDKKit/Sources/power-cc.cxx +++ b/NDKKit/Sources/power-cc.cxx @@ -7,9 +7,9 @@ * ======================================================== */ -#include -#include -#include +#include +#include +#include #include #include #include @@ -1527,7 +1527,7 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// -#include +#include #define kPrintF printf #define kSplashCxx() \ diff --git a/NDKKit/UUID.hpp b/NDKKit/UUID.hpp deleted file mode 100644 index 00b153b..0000000 --- a/NDKKit/UUID.hpp +++ /dev/null @@ -1,983 +0,0 @@ -#ifndef STDUUID_H -#define STDUUID_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus - -#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) -#define LIBUUID_CPP20_OR_GREATER -#endif - -#endif - -#ifdef LIBUUID_CPP20_OR_GREATER -#include -#else -#include -#endif - -#ifdef _WIN32 - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#ifdef UUID_TIME_GENERATOR -#include -#pragma comment(lib, "IPHLPAPI.lib") -#endif - -#elif defined(__linux__) || defined(__unix__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#elif defined(__APPLE__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#endif - -namespace uuids -{ -#ifdef __cpp_lib_span - template - using span = std::span; -#else - template - using span = gsl::span; -#endif - - namespace detail - { - template - [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept - { - if (ch >= static_cast('0') && ch <= static_cast('9')) - return static_cast(ch - static_cast('0')); - if (ch >= static_cast('a') && ch <= static_cast('f')) - return static_cast(10 + ch - static_cast('a')); - if (ch >= static_cast('A') && ch <= static_cast('F')) - return static_cast(10 + ch - static_cast('A')); - return 0; - } - - template - [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept - { - return (ch >= static_cast('0') && ch <= static_cast('9')) || - (ch >= static_cast('a') && ch <= static_cast('f')) || - (ch >= static_cast('A') && ch <= static_cast('F')); - } - - template - [[nodiscard]] constexpr std::basic_string_view to_string_view( - TChar const* str) noexcept - { - if (str) - return str; - return {}; - } - - template - [[nodiscard]] constexpr std::basic_string_view - to_string_view(StringType const& str) noexcept - { - return str; - } - - class sha1 - { - public: - using digest32_t = uint32_t[5]; - using digest8_t = uint8_t[20]; - - static constexpr unsigned int block_bytes = 64; - - [[nodiscard]] inline static uint32_t left_rotate( - uint32_t value, size_t const count) noexcept - { - return (value << count) ^ (value >> (32 - count)); - } - - sha1() - { - reset(); - } - - void reset() noexcept - { - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - m_blockByteIndex = 0; - m_byteCount = 0; - } - - void process_byte(uint8_t octet) - { - this->m_block[this->m_blockByteIndex++] = octet; - ++this->m_byteCount; - if (m_blockByteIndex == block_bytes) - { - this->m_blockByteIndex = 0; - process_block(); - } - } - - void process_block(void const* const start, void const* const end) - { - const uint8_t* begin = static_cast(start); - const uint8_t* finish = static_cast(end); - while (begin != finish) - { - process_byte(*begin); - begin++; - } - } - - void process_bytes(void const* const data, size_t const len) - { - const uint8_t* block = static_cast(data); - process_block(block, block + len); - } - - uint32_t const* get_digest(digest32_t digest) - { - size_t const bitCount = this->m_byteCount * 8; - process_byte(0x80); - if (this->m_blockByteIndex > 56) - { - while (m_blockByteIndex != 0) - { - process_byte(0); - } - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - else - { - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(static_cast((bitCount >> 24) & 0xFF)); - process_byte(static_cast((bitCount >> 16) & 0xFF)); - process_byte(static_cast((bitCount >> 8) & 0xFF)); - process_byte(static_cast((bitCount)&0xFF)); - - memcpy(digest, m_digest, 5 * sizeof(uint32_t)); - return digest; - } - - uint8_t const* get_digest_bytes(digest8_t digest) - { - digest32_t d32; - get_digest(d32); - size_t di = 0; - digest[di++] = static_cast(d32[0] >> 24); - digest[di++] = static_cast(d32[0] >> 16); - digest[di++] = static_cast(d32[0] >> 8); - digest[di++] = static_cast(d32[0] >> 0); - - digest[di++] = static_cast(d32[1] >> 24); - digest[di++] = static_cast(d32[1] >> 16); - digest[di++] = static_cast(d32[1] >> 8); - digest[di++] = static_cast(d32[1] >> 0); - - digest[di++] = static_cast(d32[2] >> 24); - digest[di++] = static_cast(d32[2] >> 16); - digest[di++] = static_cast(d32[2] >> 8); - digest[di++] = static_cast(d32[2] >> 0); - - digest[di++] = static_cast(d32[3] >> 24); - digest[di++] = static_cast(d32[3] >> 16); - digest[di++] = static_cast(d32[3] >> 8); - digest[di++] = static_cast(d32[3] >> 0); - - digest[di++] = static_cast(d32[4] >> 24); - digest[di++] = static_cast(d32[4] >> 16); - digest[di++] = static_cast(d32[4] >> 8); - digest[di++] = static_cast(d32[4] >> 0); - - return digest; - } - - private: - void process_block() - { - uint32_t w[80]; - for (size_t i = 0; i < 16; i++) - { - w[i] = static_cast(m_block[i * 4 + 0] << 24); - w[i] |= static_cast(m_block[i * 4 + 1] << 16); - w[i] |= static_cast(m_block[i * 4 + 2] << 8); - w[i] |= static_cast(m_block[i * 4 + 3]); - } - for (size_t i = 16; i < 80; i++) - { - w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); - } - - uint32_t a = m_digest[0]; - uint32_t b = m_digest[1]; - uint32_t c = m_digest[2]; - uint32_t d = m_digest[3]; - uint32_t e = m_digest[4]; - - for (std::size_t i = 0; i < 80; ++i) - { - uint32_t f = 0; - uint32_t k = 0; - - if (i < 20) - { - f = (b & c) | (~b & d); - k = 0x5A827999; - } - else if (i < 40) - { - f = b ^ c ^ d; - k = 0x6ED9EBA1; - } - else if (i < 60) - { - f = (b & c) | (b & d) | (c & d); - k = 0x8F1BBCDC; - } - else - { - f = b ^ c ^ d; - k = 0xCA62C1D6; - } - uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; - e = d; - d = c; - c = left_rotate(b, 30); - b = a; - a = temp; - } - - m_digest[0] += a; - m_digest[1] += b; - m_digest[2] += c; - m_digest[3] += d; - m_digest[4] += e; - } - - private: - digest32_t m_digest; - uint8_t m_block[64]; - size_t m_blockByteIndex; - size_t m_byteCount; - }; - - template - inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; - - template <> - inline constexpr wchar_t empty_guid[37] = - L"00000000-0000-0000-0000-000000000000"; - - template - inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; - - template <> - inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; - } // namespace detail - - // -------------------------------------------------------------------------------------------------------------------------- - // UUID format https://tools.ietf.org/html/rfc4122 - // -------------------------------------------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------------------------------------------- - // Field NDR Data Type Octet # Note - // -------------------------------------------------------------------------------------------------------------------------- - // time_low unsigned long 0 - 3 The low field - // of the timestamp. time_mid unsigned short 4 - 5 - // The middle field of the timestamp. time_hi_and_version unsigned - // short 6 - 7 The high field of the timestamp multiplexed - // with the version number. clock_seq_hi_and_reserved unsigned small 8 - // The high field of the clock sequence multiplexed with the variant. - // clock_seq_low unsigned small 9 The low - // field of the clock sequence. node character 10 - // - 15 The spatially unique node identifier. - // -------------------------------------------------------------------------------------------------------------------------- - // 0 1 2 3 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_low | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_mid | time_hi_and_version | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // |clk_seq_hi_res | clk_seq_low | node (0-1) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | node (2-5) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - // -------------------------------------------------------------------------------------------------------------------------- - // enumerations - // -------------------------------------------------------------------------------------------------------------------------- - - // indicated by a bit pattern in octet 8, marked with N in - // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx - enum class uuid_variant - { - // NCS backward compatibility (with the obsolete Apollo Network Computing - // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the - // UUID are a 48-bit timestamp (the number of 4 microsecond units of time - // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet - // is the "address family"; > the final 7 octets are a 56-bit host ID in the - // form specified by the address family - ncs, - - // RFC 4122/DCE 1.1 - // N bit pattern: 10xx - // > big-endian byte order - rfc, - - // Microsoft Corporation backward compatibility - // N bit pattern: 110x - // > little endian byte order - // > formely used in the Component Object Model (COM) library - microsoft, - - // reserved for possible future definition - // N bit pattern: 111x - reserved - }; - - // indicated by a bit pattern in octet 6, marked with M in - // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx - enum class uuid_version - { - none = 0, // only possible for nil or invalid uuids - time_based = 1, // The time-based version specified in RFC 4122 - dce_security = 2, // DCE Security version, with embedded POSIX UIDs. - name_based_md5 = - 3, // The name-based version specified in RFS 4122 with MD5 hashing - random_number_based = 4, // The randomly or pseudo-randomly generated version - // specified in RFS 4122 - name_based_sha1 = - 5 // The name-based version specified in RFS 4122 with SHA1 hashing - }; - - // Forward declare uuid & to_string so that we can declare to_string as a friend - // later. - class uuid; - template , class Allocator = std::allocator> - std::basic_string to_string(uuid const& id); - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid class - // -------------------------------------------------------------------------------------------------------------------------- - class uuid - { - public: - using value_type = uint8_t; - - constexpr uuid() noexcept = default; - - uuid(value_type (&arr)[16]) noexcept - { - std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); - } - - constexpr uuid(std::array const& arr) noexcept - : data{arr} - { - } - - explicit uuid(span bytes) - { - std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); - } - - template - explicit uuid(ForwardIterator first, ForwardIterator last) - { - if (std::distance(first, last) == 16) - std::copy(first, last, std::begin(data)); - } - - [[nodiscard]] constexpr uuid_variant variant() const noexcept - { - if ((data[8] & 0x80) == 0x00) - return uuid_variant::ncs; - else if ((data[8] & 0xC0) == 0x80) - return uuid_variant::rfc; - else if ((data[8] & 0xE0) == 0xC0) - return uuid_variant::microsoft; - else - return uuid_variant::reserved; - } - - [[nodiscard]] constexpr uuid_version version() const noexcept - { - if ((data[6] & 0xF0) == 0x10) - return uuid_version::time_based; - else if ((data[6] & 0xF0) == 0x20) - return uuid_version::dce_security; - else if ((data[6] & 0xF0) == 0x30) - return uuid_version::name_based_md5; - else if ((data[6] & 0xF0) == 0x40) - return uuid_version::random_number_based; - else if ((data[6] & 0xF0) == 0x50) - return uuid_version::name_based_sha1; - else - return uuid_version::none; - } - - [[nodiscard]] constexpr bool is_nil() const noexcept - { - for (size_t i = 0; i < data.size(); ++i) - if (data[i] != 0) - return false; - return true; - } - - void swap(uuid& other) noexcept - { - data.swap(other.data); - } - - [[nodiscard]] inline span as_bytes() const - { - return span( - reinterpret_cast(data.data()), 16); - } - - template - [[nodiscard]] constexpr static bool is_valid_uuid( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - if (str.empty()) - return false; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return false; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return false; - } - - if (firstDigit) - { - firstDigit = false; - } - else - { - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return false; - } - - return true; - } - - template - [[nodiscard]] constexpr static std::optional from_string( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - std::array data{{0}}; - - if (str.empty()) - return {}; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return {}; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return {}; - } - - if (firstDigit) - { - data[index] = static_cast(detail::hex2char(str[i]) << 4); - firstDigit = false; - } - else - { - data[index] = - static_cast(data[index] | detail::hex2char(str[i])); - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return {}; - } - - return uuid{data}; - } - - private: - std::array data{{0}}; - - friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; - friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; - - template - friend std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id); - - template - friend std::basic_string to_string(uuid const& id); - - friend std::hash; - }; - - // -------------------------------------------------------------------------------------------------------------------------- - // operators and non-member functions - // -------------------------------------------------------------------------------------------------------------------------- - - [[nodiscard]] inline bool operator==(uuid const& lhs, - uuid const& rhs) noexcept - { - return lhs.data == rhs.data; - } - - [[nodiscard]] inline bool operator!=(uuid const& lhs, - uuid const& rhs) noexcept - { - return !(lhs == rhs); - } - - [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept - { - return lhs.data < rhs.data; - } - - template - [[nodiscard]] inline std::basic_string to_string( - uuid const& id) - { - std::basic_string uustr{detail::empty_guid}; - - for (size_t i = 0, index = 0; i < 36; ++i) - { - if (i == 8 || i == 13 || i == 18 || i == 23) - { - continue; - } - uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; - uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; - index++; - } - - return uustr; - } - - template - std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id) - { - s << to_string(id); - return s; - } - - inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept - { - lhs.swap(rhs); - } - - // -------------------------------------------------------------------------------------------------------------------------- - // namespace IDs that could be used for generating name-based uuids - // -------------------------------------------------------------------------------------------------------------------------- - - // Name string is a fully-qualified domain name - static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is a URL - static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an ISO OID (See https://oidref.com/, - // https://en.wikipedia.org/wiki/Object_identifier) - static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an X.500 DN, in DER or a text output format (See - // https://en.wikipedia.org/wiki/X.500, - // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) - static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid generators - // -------------------------------------------------------------------------------------------------------------------------- - -#ifdef UUID_SYSTEM_GENERATOR - class uuid_system_generator - { - public: - using result_type = uuid; - - uuid operator()() - { -#ifdef _WIN32 - - GUID newId; - HRESULT hr = ::CoCreateGuid(&newId); - - if (FAILED(hr)) - { - throw std::system_error(hr, std::system_category(), - "CoCreateGuid failed"); - } - - std::array bytes = { - {static_cast((newId.Data1 >> 24) & 0xFF), - static_cast((newId.Data1 >> 16) & 0xFF), - static_cast((newId.Data1 >> 8) & 0xFF), - static_cast((newId.Data1) & 0xFF), - - (unsigned char)((newId.Data2 >> 8) & 0xFF), - (unsigned char)((newId.Data2) & 0xFF), - - (unsigned char)((newId.Data3 >> 8) & 0xFF), - (unsigned char)((newId.Data3) & 0xFF), - - newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], - newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__linux__) || defined(__unix__) - - uuid_t id; - uuid_generate(id); - - std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], - id[6], id[7], id[8], id[9], id[10], - id[11], id[12], id[13], id[14], id[15]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__APPLE__) - auto newId = CFUUIDCreate(NULL); - auto bytes = CFUUIDGetUUIDBytes(newId); - CFRelease(newId); - - std::array arrbytes = { - {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, - bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, - bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, - bytes.byte15}}; - return uuid{std::begin(arrbytes), std::end(arrbytes)}; -#else - return uuid{}; -#endif - } - }; -#endif - - template - class basic_uuid_random_generator - { - public: - using engine_type = UniformRandomNumberGenerator; - - explicit basic_uuid_random_generator(engine_type& gen) - : generator(&gen, [](auto) {}) - { - } - explicit basic_uuid_random_generator(engine_type* gen) - : generator(gen, [](auto) {}) - { - } - - [[nodiscard]] uuid operator()() - { - alignas(uint32_t) uint8_t bytes[16]; - for (int i = 0; i < 16; i += 4) - *reinterpret_cast(bytes + i) = distribution(*generator); - - // variant must be 10xxxxxx - bytes[8] &= 0xBF; - bytes[8] |= 0x80; - - // version must be 0100xxxx - bytes[6] &= 0x4F; - bytes[6] |= 0x40; - - return uuid{std::begin(bytes), std::end(bytes)}; - } - - private: - std::uniform_int_distribution distribution; - std::shared_ptr generator; - }; - - using uuid_random_generator = basic_uuid_random_generator; - - class uuid_name_generator - { - public: - explicit uuid_name_generator(uuid const& namespace_uuid) noexcept - : nsuuid(namespace_uuid) - { - } - - template - [[nodiscard]] uuid operator()(StringType const& name) - { - reset(); - process_characters(detail::to_string_view(name)); - return make_uuid(); - } - - private: - void reset() - { - hasher.reset(); - std::byte bytes[16]; - auto nsbytes = nsuuid.as_bytes(); - std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); - hasher.process_bytes(bytes, 16); - } - - template - void process_characters(std::basic_string_view const str) - { - for (uint32_t c : str) - { - hasher.process_byte(static_cast(c & 0xFF)); - if constexpr (!std::is_same_v) - { - hasher.process_byte(static_cast((c >> 8) & 0xFF)); - hasher.process_byte(static_cast((c >> 16) & 0xFF)); - hasher.process_byte(static_cast((c >> 24) & 0xFF)); - } - } - } - - [[nodiscard]] uuid make_uuid() - { - detail::sha1::digest8_t digest; - hasher.get_digest_bytes(digest); - - // variant must be 0b10xxxxxx - digest[8] &= 0xBF; - digest[8] |= 0x80; - - // version must be 0b0101xxxx - digest[6] &= 0x5F; - digest[6] |= 0x50; - - return uuid{digest, digest + 16}; - } - - private: - uuid nsuuid; - detail::sha1 hasher; - }; - -#ifdef UUID_TIME_GENERATOR - // !!! DO NOT USE THIS IN PRODUCTION - // this implementation is unreliable for good uuids - class uuid_time_generator - { - using mac_address = std::array; - - std::optional device_address; - - [[nodiscard]] bool get_mac_address() - { - if (device_address.has_value()) - { - return true; - } - -#ifdef _WIN32 - DWORD len = 0; - auto ret = GetAdaptersInfo(nullptr, &len); - if (ret != ERROR_BUFFER_OVERFLOW) - return false; - std::vector buf(len); - auto pips = reinterpret_cast(&buf.front()); - ret = GetAdaptersInfo(pips, &len); - if (ret != ERROR_SUCCESS) - return false; - mac_address addr; - std::copy(pips->Address, pips->Address + 6, std::begin(addr)); - device_address = addr; -#endif - - return device_address.has_value(); - } - - [[nodiscard]] long long get_time_intervals() - { - auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); - auto diff = std::chrono::system_clock::now() - start; - auto ns = - std::chrono::duration_cast(diff).count(); - return ns / 100; - } - - [[nodiscard]] static unsigned short get_clock_sequence() - { - static std::mt19937 clock_gen(std::random_device{}()); - static std::uniform_int_distribution clock_dis; - static std::atomic_ushort clock_sequence = clock_dis(clock_gen); - return clock_sequence++; - } - - public: - [[nodiscard]] uuid operator()() - { - if (get_mac_address()) - { - std::array data; - - auto tm = get_time_intervals(); - - auto clock_seq = get_clock_sequence(); - - auto ptm = reinterpret_cast(&tm); - - memcpy(&data[0], ptm + 4, 4); - memcpy(&data[4], ptm + 2, 2); - memcpy(&data[6], ptm, 2); - - memcpy(&data[8], &clock_seq, 2); - - // variant must be 0b10xxxxxx - data[8] &= 0xBF; - data[8] |= 0x80; - - // version must be 0b0001xxxx - data[6] &= 0x1F; - data[6] |= 0x10; - - memcpy(&data[10], &device_address.value()[0], 6); - - return uuids::uuid{std::cbegin(data), std::cend(data)}; - } - - return {}; - } - }; -#endif -} // namespace uuids - -namespace std -{ - template <> - struct hash - { - using argument_type = uuids::uuid; - using result_type = std::size_t; - - [[nodiscard]] result_type operator()(argument_type const& uuid) const - { -#ifdef UUID_HASH_STRING_BASED - std::hash hasher; - return static_cast(hasher(uuids::to_string(uuid))); -#else - uint64_t l = static_cast(uuid.data[0]) << 56 | - static_cast(uuid.data[1]) << 48 | - static_cast(uuid.data[2]) << 40 | - static_cast(uuid.data[3]) << 32 | - static_cast(uuid.data[4]) << 24 | - static_cast(uuid.data[5]) << 16 | - static_cast(uuid.data[6]) << 8 | - static_cast(uuid.data[7]); - uint64_t h = static_cast(uuid.data[8]) << 56 | - static_cast(uuid.data[9]) << 48 | - static_cast(uuid.data[10]) << 40 | - static_cast(uuid.data[11]) << 32 | - static_cast(uuid.data[12]) << 24 | - static_cast(uuid.data[13]) << 16 | - static_cast(uuid.data[14]) << 8 | - static_cast(uuid.data[15]); - - if constexpr (sizeof(result_type) > 4) - { - return result_type(l ^ h); - } - else - { - uint64_t hash64 = l ^ h; - return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); - } -#endif - } - }; -} // namespace std - -#endif /* STDUUID_H */ \ No newline at end of file diff --git a/NDKKit/UUID.hxx b/NDKKit/UUID.hxx new file mode 100644 index 0000000..00b153b --- /dev/null +++ b/NDKKit/UUID.hxx @@ -0,0 +1,983 @@ +#ifndef STDUUID_H +#define STDUUID_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + +#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define LIBUUID_CPP20_OR_GREATER +#endif + +#endif + +#ifdef LIBUUID_CPP20_OR_GREATER +#include +#else +#include +#endif + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#ifdef UUID_TIME_GENERATOR +#include +#pragma comment(lib, "IPHLPAPI.lib") +#endif + +#elif defined(__linux__) || defined(__unix__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#elif defined(__APPLE__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#endif + +namespace uuids +{ +#ifdef __cpp_lib_span + template + using span = std::span; +#else + template + using span = gsl::span; +#endif + + namespace detail + { + template + [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept + { + if (ch >= static_cast('0') && ch <= static_cast('9')) + return static_cast(ch - static_cast('0')); + if (ch >= static_cast('a') && ch <= static_cast('f')) + return static_cast(10 + ch - static_cast('a')); + if (ch >= static_cast('A') && ch <= static_cast('F')) + return static_cast(10 + ch - static_cast('A')); + return 0; + } + + template + [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept + { + return (ch >= static_cast('0') && ch <= static_cast('9')) || + (ch >= static_cast('a') && ch <= static_cast('f')) || + (ch >= static_cast('A') && ch <= static_cast('F')); + } + + template + [[nodiscard]] constexpr std::basic_string_view to_string_view( + TChar const* str) noexcept + { + if (str) + return str; + return {}; + } + + template + [[nodiscard]] constexpr std::basic_string_view + to_string_view(StringType const& str) noexcept + { + return str; + } + + class sha1 + { + public: + using digest32_t = uint32_t[5]; + using digest8_t = uint8_t[20]; + + static constexpr unsigned int block_bytes = 64; + + [[nodiscard]] inline static uint32_t left_rotate( + uint32_t value, size_t const count) noexcept + { + return (value << count) ^ (value >> (32 - count)); + } + + sha1() + { + reset(); + } + + void reset() noexcept + { + m_digest[0] = 0x67452301; + m_digest[1] = 0xEFCDAB89; + m_digest[2] = 0x98BADCFE; + m_digest[3] = 0x10325476; + m_digest[4] = 0xC3D2E1F0; + m_blockByteIndex = 0; + m_byteCount = 0; + } + + void process_byte(uint8_t octet) + { + this->m_block[this->m_blockByteIndex++] = octet; + ++this->m_byteCount; + if (m_blockByteIndex == block_bytes) + { + this->m_blockByteIndex = 0; + process_block(); + } + } + + void process_block(void const* const start, void const* const end) + { + const uint8_t* begin = static_cast(start); + const uint8_t* finish = static_cast(end); + while (begin != finish) + { + process_byte(*begin); + begin++; + } + } + + void process_bytes(void const* const data, size_t const len) + { + const uint8_t* block = static_cast(data); + process_block(block, block + len); + } + + uint32_t const* get_digest(digest32_t digest) + { + size_t const bitCount = this->m_byteCount * 8; + process_byte(0x80); + if (this->m_blockByteIndex > 56) + { + while (m_blockByteIndex != 0) + { + process_byte(0); + } + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + else + { + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(static_cast((bitCount >> 24) & 0xFF)); + process_byte(static_cast((bitCount >> 16) & 0xFF)); + process_byte(static_cast((bitCount >> 8) & 0xFF)); + process_byte(static_cast((bitCount)&0xFF)); + + memcpy(digest, m_digest, 5 * sizeof(uint32_t)); + return digest; + } + + uint8_t const* get_digest_bytes(digest8_t digest) + { + digest32_t d32; + get_digest(d32); + size_t di = 0; + digest[di++] = static_cast(d32[0] >> 24); + digest[di++] = static_cast(d32[0] >> 16); + digest[di++] = static_cast(d32[0] >> 8); + digest[di++] = static_cast(d32[0] >> 0); + + digest[di++] = static_cast(d32[1] >> 24); + digest[di++] = static_cast(d32[1] >> 16); + digest[di++] = static_cast(d32[1] >> 8); + digest[di++] = static_cast(d32[1] >> 0); + + digest[di++] = static_cast(d32[2] >> 24); + digest[di++] = static_cast(d32[2] >> 16); + digest[di++] = static_cast(d32[2] >> 8); + digest[di++] = static_cast(d32[2] >> 0); + + digest[di++] = static_cast(d32[3] >> 24); + digest[di++] = static_cast(d32[3] >> 16); + digest[di++] = static_cast(d32[3] >> 8); + digest[di++] = static_cast(d32[3] >> 0); + + digest[di++] = static_cast(d32[4] >> 24); + digest[di++] = static_cast(d32[4] >> 16); + digest[di++] = static_cast(d32[4] >> 8); + digest[di++] = static_cast(d32[4] >> 0); + + return digest; + } + + private: + void process_block() + { + uint32_t w[80]; + for (size_t i = 0; i < 16; i++) + { + w[i] = static_cast(m_block[i * 4 + 0] << 24); + w[i] |= static_cast(m_block[i * 4 + 1] << 16); + w[i] |= static_cast(m_block[i * 4 + 2] << 8); + w[i] |= static_cast(m_block[i * 4 + 3]); + } + for (size_t i = 16; i < 80; i++) + { + w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); + } + + uint32_t a = m_digest[0]; + uint32_t b = m_digest[1]; + uint32_t c = m_digest[2]; + uint32_t d = m_digest[3]; + uint32_t e = m_digest[4]; + + for (std::size_t i = 0; i < 80; ++i) + { + uint32_t f = 0; + uint32_t k = 0; + + if (i < 20) + { + f = (b & c) | (~b & d); + k = 0x5A827999; + } + else if (i < 40) + { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } + else if (i < 60) + { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } + else + { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; + e = d; + d = c; + c = left_rotate(b, 30); + b = a; + a = temp; + } + + m_digest[0] += a; + m_digest[1] += b; + m_digest[2] += c; + m_digest[3] += d; + m_digest[4] += e; + } + + private: + digest32_t m_digest; + uint8_t m_block[64]; + size_t m_blockByteIndex; + size_t m_byteCount; + }; + + template + inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; + + template <> + inline constexpr wchar_t empty_guid[37] = + L"00000000-0000-0000-0000-000000000000"; + + template + inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; + + template <> + inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; + } // namespace detail + + // -------------------------------------------------------------------------------------------------------------------------- + // UUID format https://tools.ietf.org/html/rfc4122 + // -------------------------------------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------------------------------------- + // Field NDR Data Type Octet # Note + // -------------------------------------------------------------------------------------------------------------------------- + // time_low unsigned long 0 - 3 The low field + // of the timestamp. time_mid unsigned short 4 - 5 + // The middle field of the timestamp. time_hi_and_version unsigned + // short 6 - 7 The high field of the timestamp multiplexed + // with the version number. clock_seq_hi_and_reserved unsigned small 8 + // The high field of the clock sequence multiplexed with the variant. + // clock_seq_low unsigned small 9 The low + // field of the clock sequence. node character 10 + // - 15 The spatially unique node identifier. + // -------------------------------------------------------------------------------------------------------------------------- + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_low | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_mid | time_hi_and_version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |clk_seq_hi_res | clk_seq_low | node (0-1) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | node (2-5) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + // -------------------------------------------------------------------------------------------------------------------------- + // enumerations + // -------------------------------------------------------------------------------------------------------------------------- + + // indicated by a bit pattern in octet 8, marked with N in + // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx + enum class uuid_variant + { + // NCS backward compatibility (with the obsolete Apollo Network Computing + // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the + // UUID are a 48-bit timestamp (the number of 4 microsecond units of time + // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet + // is the "address family"; > the final 7 octets are a 56-bit host ID in the + // form specified by the address family + ncs, + + // RFC 4122/DCE 1.1 + // N bit pattern: 10xx + // > big-endian byte order + rfc, + + // Microsoft Corporation backward compatibility + // N bit pattern: 110x + // > little endian byte order + // > formely used in the Component Object Model (COM) library + microsoft, + + // reserved for possible future definition + // N bit pattern: 111x + reserved + }; + + // indicated by a bit pattern in octet 6, marked with M in + // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx + enum class uuid_version + { + none = 0, // only possible for nil or invalid uuids + time_based = 1, // The time-based version specified in RFC 4122 + dce_security = 2, // DCE Security version, with embedded POSIX UIDs. + name_based_md5 = + 3, // The name-based version specified in RFS 4122 with MD5 hashing + random_number_based = 4, // The randomly or pseudo-randomly generated version + // specified in RFS 4122 + name_based_sha1 = + 5 // The name-based version specified in RFS 4122 with SHA1 hashing + }; + + // Forward declare uuid & to_string so that we can declare to_string as a friend + // later. + class uuid; + template , class Allocator = std::allocator> + std::basic_string to_string(uuid const& id); + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid class + // -------------------------------------------------------------------------------------------------------------------------- + class uuid + { + public: + using value_type = uint8_t; + + constexpr uuid() noexcept = default; + + uuid(value_type (&arr)[16]) noexcept + { + std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); + } + + constexpr uuid(std::array const& arr) noexcept + : data{arr} + { + } + + explicit uuid(span bytes) + { + std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); + } + + template + explicit uuid(ForwardIterator first, ForwardIterator last) + { + if (std::distance(first, last) == 16) + std::copy(first, last, std::begin(data)); + } + + [[nodiscard]] constexpr uuid_variant variant() const noexcept + { + if ((data[8] & 0x80) == 0x00) + return uuid_variant::ncs; + else if ((data[8] & 0xC0) == 0x80) + return uuid_variant::rfc; + else if ((data[8] & 0xE0) == 0xC0) + return uuid_variant::microsoft; + else + return uuid_variant::reserved; + } + + [[nodiscard]] constexpr uuid_version version() const noexcept + { + if ((data[6] & 0xF0) == 0x10) + return uuid_version::time_based; + else if ((data[6] & 0xF0) == 0x20) + return uuid_version::dce_security; + else if ((data[6] & 0xF0) == 0x30) + return uuid_version::name_based_md5; + else if ((data[6] & 0xF0) == 0x40) + return uuid_version::random_number_based; + else if ((data[6] & 0xF0) == 0x50) + return uuid_version::name_based_sha1; + else + return uuid_version::none; + } + + [[nodiscard]] constexpr bool is_nil() const noexcept + { + for (size_t i = 0; i < data.size(); ++i) + if (data[i] != 0) + return false; + return true; + } + + void swap(uuid& other) noexcept + { + data.swap(other.data); + } + + [[nodiscard]] inline span as_bytes() const + { + return span( + reinterpret_cast(data.data()), 16); + } + + template + [[nodiscard]] constexpr static bool is_valid_uuid( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + if (str.empty()) + return false; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return false; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return false; + } + + if (firstDigit) + { + firstDigit = false; + } + else + { + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return false; + } + + return true; + } + + template + [[nodiscard]] constexpr static std::optional from_string( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + std::array data{{0}}; + + if (str.empty()) + return {}; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return {}; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return {}; + } + + if (firstDigit) + { + data[index] = static_cast(detail::hex2char(str[i]) << 4); + firstDigit = false; + } + else + { + data[index] = + static_cast(data[index] | detail::hex2char(str[i])); + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return {}; + } + + return uuid{data}; + } + + private: + std::array data{{0}}; + + friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; + friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; + + template + friend std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id); + + template + friend std::basic_string to_string(uuid const& id); + + friend std::hash; + }; + + // -------------------------------------------------------------------------------------------------------------------------- + // operators and non-member functions + // -------------------------------------------------------------------------------------------------------------------------- + + [[nodiscard]] inline bool operator==(uuid const& lhs, + uuid const& rhs) noexcept + { + return lhs.data == rhs.data; + } + + [[nodiscard]] inline bool operator!=(uuid const& lhs, + uuid const& rhs) noexcept + { + return !(lhs == rhs); + } + + [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept + { + return lhs.data < rhs.data; + } + + template + [[nodiscard]] inline std::basic_string to_string( + uuid const& id) + { + std::basic_string uustr{detail::empty_guid}; + + for (size_t i = 0, index = 0; i < 36; ++i) + { + if (i == 8 || i == 13 || i == 18 || i == 23) + { + continue; + } + uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; + uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; + index++; + } + + return uustr; + } + + template + std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id) + { + s << to_string(id); + return s; + } + + inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept + { + lhs.swap(rhs); + } + + // -------------------------------------------------------------------------------------------------------------------------- + // namespace IDs that could be used for generating name-based uuids + // -------------------------------------------------------------------------------------------------------------------------- + + // Name string is a fully-qualified domain name + static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is a URL + static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an ISO OID (See https://oidref.com/, + // https://en.wikipedia.org/wiki/Object_identifier) + static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an X.500 DN, in DER or a text output format (See + // https://en.wikipedia.org/wiki/X.500, + // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) + static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid generators + // -------------------------------------------------------------------------------------------------------------------------- + +#ifdef UUID_SYSTEM_GENERATOR + class uuid_system_generator + { + public: + using result_type = uuid; + + uuid operator()() + { +#ifdef _WIN32 + + GUID newId; + HRESULT hr = ::CoCreateGuid(&newId); + + if (FAILED(hr)) + { + throw std::system_error(hr, std::system_category(), + "CoCreateGuid failed"); + } + + std::array bytes = { + {static_cast((newId.Data1 >> 24) & 0xFF), + static_cast((newId.Data1 >> 16) & 0xFF), + static_cast((newId.Data1 >> 8) & 0xFF), + static_cast((newId.Data1) & 0xFF), + + (unsigned char)((newId.Data2 >> 8) & 0xFF), + (unsigned char)((newId.Data2) & 0xFF), + + (unsigned char)((newId.Data3 >> 8) & 0xFF), + (unsigned char)((newId.Data3) & 0xFF), + + newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], + newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__linux__) || defined(__unix__) + + uuid_t id; + uuid_generate(id); + + std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], + id[6], id[7], id[8], id[9], id[10], + id[11], id[12], id[13], id[14], id[15]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__APPLE__) + auto newId = CFUUIDCreate(NULL); + auto bytes = CFUUIDGetUUIDBytes(newId); + CFRelease(newId); + + std::array arrbytes = { + {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, + bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, + bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, + bytes.byte15}}; + return uuid{std::begin(arrbytes), std::end(arrbytes)}; +#else + return uuid{}; +#endif + } + }; +#endif + + template + class basic_uuid_random_generator + { + public: + using engine_type = UniformRandomNumberGenerator; + + explicit basic_uuid_random_generator(engine_type& gen) + : generator(&gen, [](auto) {}) + { + } + explicit basic_uuid_random_generator(engine_type* gen) + : generator(gen, [](auto) {}) + { + } + + [[nodiscard]] uuid operator()() + { + alignas(uint32_t) uint8_t bytes[16]; + for (int i = 0; i < 16; i += 4) + *reinterpret_cast(bytes + i) = distribution(*generator); + + // variant must be 10xxxxxx + bytes[8] &= 0xBF; + bytes[8] |= 0x80; + + // version must be 0100xxxx + bytes[6] &= 0x4F; + bytes[6] |= 0x40; + + return uuid{std::begin(bytes), std::end(bytes)}; + } + + private: + std::uniform_int_distribution distribution; + std::shared_ptr generator; + }; + + using uuid_random_generator = basic_uuid_random_generator; + + class uuid_name_generator + { + public: + explicit uuid_name_generator(uuid const& namespace_uuid) noexcept + : nsuuid(namespace_uuid) + { + } + + template + [[nodiscard]] uuid operator()(StringType const& name) + { + reset(); + process_characters(detail::to_string_view(name)); + return make_uuid(); + } + + private: + void reset() + { + hasher.reset(); + std::byte bytes[16]; + auto nsbytes = nsuuid.as_bytes(); + std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); + hasher.process_bytes(bytes, 16); + } + + template + void process_characters(std::basic_string_view const str) + { + for (uint32_t c : str) + { + hasher.process_byte(static_cast(c & 0xFF)); + if constexpr (!std::is_same_v) + { + hasher.process_byte(static_cast((c >> 8) & 0xFF)); + hasher.process_byte(static_cast((c >> 16) & 0xFF)); + hasher.process_byte(static_cast((c >> 24) & 0xFF)); + } + } + } + + [[nodiscard]] uuid make_uuid() + { + detail::sha1::digest8_t digest; + hasher.get_digest_bytes(digest); + + // variant must be 0b10xxxxxx + digest[8] &= 0xBF; + digest[8] |= 0x80; + + // version must be 0b0101xxxx + digest[6] &= 0x5F; + digest[6] |= 0x50; + + return uuid{digest, digest + 16}; + } + + private: + uuid nsuuid; + detail::sha1 hasher; + }; + +#ifdef UUID_TIME_GENERATOR + // !!! DO NOT USE THIS IN PRODUCTION + // this implementation is unreliable for good uuids + class uuid_time_generator + { + using mac_address = std::array; + + std::optional device_address; + + [[nodiscard]] bool get_mac_address() + { + if (device_address.has_value()) + { + return true; + } + +#ifdef _WIN32 + DWORD len = 0; + auto ret = GetAdaptersInfo(nullptr, &len); + if (ret != ERROR_BUFFER_OVERFLOW) + return false; + std::vector buf(len); + auto pips = reinterpret_cast(&buf.front()); + ret = GetAdaptersInfo(pips, &len); + if (ret != ERROR_SUCCESS) + return false; + mac_address addr; + std::copy(pips->Address, pips->Address + 6, std::begin(addr)); + device_address = addr; +#endif + + return device_address.has_value(); + } + + [[nodiscard]] long long get_time_intervals() + { + auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); + auto diff = std::chrono::system_clock::now() - start; + auto ns = + std::chrono::duration_cast(diff).count(); + return ns / 100; + } + + [[nodiscard]] static unsigned short get_clock_sequence() + { + static std::mt19937 clock_gen(std::random_device{}()); + static std::uniform_int_distribution clock_dis; + static std::atomic_ushort clock_sequence = clock_dis(clock_gen); + return clock_sequence++; + } + + public: + [[nodiscard]] uuid operator()() + { + if (get_mac_address()) + { + std::array data; + + auto tm = get_time_intervals(); + + auto clock_seq = get_clock_sequence(); + + auto ptm = reinterpret_cast(&tm); + + memcpy(&data[0], ptm + 4, 4); + memcpy(&data[4], ptm + 2, 2); + memcpy(&data[6], ptm, 2); + + memcpy(&data[8], &clock_seq, 2); + + // variant must be 0b10xxxxxx + data[8] &= 0xBF; + data[8] |= 0x80; + + // version must be 0b0001xxxx + data[6] &= 0x1F; + data[6] |= 0x10; + + memcpy(&data[10], &device_address.value()[0], 6); + + return uuids::uuid{std::cbegin(data), std::cend(data)}; + } + + return {}; + } + }; +#endif +} // namespace uuids + +namespace std +{ + template <> + struct hash + { + using argument_type = uuids::uuid; + using result_type = std::size_t; + + [[nodiscard]] result_type operator()(argument_type const& uuid) const + { +#ifdef UUID_HASH_STRING_BASED + std::hash hasher; + return static_cast(hasher(uuids::to_string(uuid))); +#else + uint64_t l = static_cast(uuid.data[0]) << 56 | + static_cast(uuid.data[1]) << 48 | + static_cast(uuid.data[2]) << 40 | + static_cast(uuid.data[3]) << 32 | + static_cast(uuid.data[4]) << 24 | + static_cast(uuid.data[5]) << 16 | + static_cast(uuid.data[6]) << 8 | + static_cast(uuid.data[7]); + uint64_t h = static_cast(uuid.data[8]) << 56 | + static_cast(uuid.data[9]) << 48 | + static_cast(uuid.data[10]) << 40 | + static_cast(uuid.data[11]) << 32 | + static_cast(uuid.data[12]) << 24 | + static_cast(uuid.data[13]) << 16 | + static_cast(uuid.data[14]) << 8 | + static_cast(uuid.data[15]); + + if constexpr (sizeof(result_type) > 4) + { + return result_type(l ^ h); + } + else + { + uint64_t hash64 = l ^ h; + return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); + } +#endif + } + }; +} // namespace std + +#endif /* STDUUID_H */ \ No newline at end of file diff --git a/NDKKit/Version.hpp b/NDKKit/Version.hpp deleted file mode 100644 index 38fd537..0000000 --- a/NDKKit/Version.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#define kDistVersion "v1.22" -#define kDistRelease "Havok" \ No newline at end of file diff --git a/NDKKit/Version.hxx b/NDKKit/Version.hxx new file mode 100644 index 0000000..38fd537 --- /dev/null +++ b/NDKKit/Version.hxx @@ -0,0 +1,4 @@ +#pragma once + +#define kDistVersion "v1.22" +#define kDistRelease "Havok" \ No newline at end of file -- cgit v1.2.3