From 63ae93c6e68c15de350829b0d74074a64e8d444a Mon Sep 17 00:00:00 2001 From: Brett Date: Tue, 24 Oct 2023 21:43:22 -0400 Subject: [PATCH] move around to bytes and make it faster --- include/blt/nbt/nbt.h | 32 +++-------------- include/blt/std/memory.h | 75 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 29 deletions(-) diff --git a/include/blt/nbt/nbt.h b/include/blt/nbt/nbt.h index c3fb6e4..8adc8c2 100755 --- a/include/blt/nbt/nbt.h +++ b/include/blt/nbt/nbt.h @@ -12,10 +12,12 @@ #include #include #include +#include #include "blt/std/format.h" #include "blt/std/filesystem.h" #include "blt/std/logging.h" +#include "blt/std/memory.h" #include @@ -25,36 +27,10 @@ namespace blt::nbt { std::string readUTF8String(blt::fs::block_reader& stream); - // Used to grab the byte-data of any T element. Defaults to Big Endian, however can be configured to use little endian - template - inline static int toBytes(const T& in, char* out) { - std::memcpy(out, (void*) &in, sizeof(T)); - - if constexpr (std::endian::native == std::endian::little) { - for (size_t i = 0; i < sizeof(T) / 2; i++) - std::swap(out[i], out[sizeof(T) - 1 - i]); - } - - return 0; - } - - // Used to cast the binary data of any T object, into a T object. - template - inline static int fromBytes(const char* in, T* out) { - memcpy(out, in, sizeof(T)); - - if constexpr (std::endian::native == std::endian::little) { - for (size_t i = 0; i < sizeof(T) / 2; i++) - std::swap(((char*) (out))[i], ((char*) (out))[sizeof(T) - 1 - i]); - } - - return 0; - } - template inline static void writeData(blt::fs::block_writer& out, const T& d){ char data[sizeof(T)]; - toBytes(d, data); + mem::toBytes(d, data); out.write(data, sizeof(T)); } @@ -62,7 +38,7 @@ namespace blt::nbt { inline static void readData(blt::fs::block_reader& in, T& d) { char data[sizeof(T)]; in.read(data, sizeof(T)); - fromBytes(data, &d); + mem::fromBytes(data, &d); } enum class nbt_tag : char { diff --git a/include/blt/std/memory.h b/include/blt/std/memory.h index 1c1fcb8..bf1ee68 100755 --- a/include/blt/std/memory.h +++ b/include/blt/std/memory.h @@ -10,12 +10,85 @@ #include #include #include -#include #include "queue.h" +#include +#include +#include +#include +#include +#include +#include + +#if defined(__clang__) || defined(__llvm__) || defined(__GNUC__) || defined(__GNUG__) + + #include + + #define SWAP16(val) bswap_16(val) + #define SWAP32(val) bswap_32(val) + #define SWAP64(val) bswap_64(val) + #define ENDIAN_LOOKUP(little_endian) (std::endian::native == std::endian::little && !little_endian) || \ + (std::endian::native == std::endian::big && little_endian) +#elif defined(_MSC_VER) + #include + #define SWAP16(val) _byteswap_ushort(val) + #define SWAP32(val) _byteswap_ulong(val) + #define SWAP64(val) _byteswap_uint64(val) + #define ENDIAN_LOOKUP(little_endian) !little_endian +#endif namespace blt { + namespace mem + { + // Used to grab the byte-data of any T element. Defaults to Big Endian, however can be configured to use little endian + template + inline static int toBytes(const T& in, BYTE_TYPE* out) + { + if constexpr (!(std::is_same_v || std::is_same_v)) + static_assert("Must provide a signed/unsigned int8 type"); + std::memcpy(out, (void*) &in, sizeof(T)); + + if constexpr (ENDIAN_LOOKUP(little_endian)) + { + // TODO: this but better. + for (size_t i = 0; i < sizeof(T) / 2; i++) + std::swap(out[i], out[sizeof(T) - 1 - i]); + } + + return 0; + } + + // Used to cast the binary data of any T object, into a T object. Assumes data is in big ending (configurable) + template + inline static int fromBytes(const BYTE_TYPE* in, T& out) + { + if constexpr (!(std::is_same_v || std::is_same_v)) + static_assert("Must provide a signed/unsigned int8 type"); + + std::array data; + std::memcpy(data.data(), in, sizeof(T)); + + if constexpr (ENDIAN_LOOKUP(little_endian)) + { + // if we need to swap find the best way to do so + if constexpr (std::is_same_v || std::is_same_v) + out = SWAP16(*reinterpret_cast(data.data())); + else if constexpr (std::is_same_v || std::is_same_v) + out = SWAP32(*reinterpret_cast(data.data())); + else if constexpr (std::is_same_v || std::is_same_v) + out = SWAP64(*reinterpret_cast(data.data())); + else + { + std::reverse(data.begin(), data.end()); + out = *reinterpret_cast(data.data()); + } + } + + return 0; + } + } + template struct ptr_iterator {