diff options
author | rtk0c <[email protected]> | 2022-06-30 21:38:53 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-06-30 21:38:53 -0700 |
commit | 7fe47a9d5b1727a61dc724523b530762f6d6ba19 (patch) | |
tree | e95be6e66db504ed06d00b72c579565bab873277 /app/source/Cplt/Utils/IO/DataStream.cpp | |
parent | 2cf952088d375ac8b2f45b144462af0953436cff (diff) |
Restructure project
Diffstat (limited to 'app/source/Cplt/Utils/IO/DataStream.cpp')
-rw-r--r-- | app/source/Cplt/Utils/IO/DataStream.cpp | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/app/source/Cplt/Utils/IO/DataStream.cpp b/app/source/Cplt/Utils/IO/DataStream.cpp new file mode 100644 index 0000000..c0797e3 --- /dev/null +++ b/app/source/Cplt/Utils/IO/DataStream.cpp @@ -0,0 +1,283 @@ +#include "DataStream.hpp" + +#include <bit> +#include <limits> +#include <utility> + +static_assert(std::numeric_limits<float>::is_iec559, "Non IEE754/IEC559 'float' is not supported."); +static_assert(std::numeric_limits<double>::is_iec559, "Non IEE754/IEC559 'double' is not supported."); + +static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big, "Mixed endian is not supported."); + +// Reading/writing signed integer byte-by-byte is fine, since the representation got fixed to 2's complements in C++20 + +static uint16_t ByteSwap(uint16_t n) +{ + auto bytes = reinterpret_cast<std::byte*>(n); + std::swap(bytes[0], bytes[1]); + return n; +} + +static uint32_t ByteSwap(uint32_t n) +{ +#ifdef _MSC_VER + return _byteswap_ulong(n); +#else + return __builtin_bswap32(n); +#endif +} + +static uint64_t ByteSwap(uint64_t n) +{ +#ifdef _MSC_VER + return _byteswap_uint64(n); +#else + return __builtin_bswap64(n); +#endif +} + +template <class TSigned> +static TSigned ByteSwap(TSigned n) +{ + using Unsigned = std::make_unsigned_t<TSigned>; + + auto swapped = ::ByteSwap(std::bit_cast<Unsigned>(n)); + return std::bit_cast<TSigned>(swapped); +} + +std::endian BaseDataStream::GetEndianness() const +{ + return mEndian; +} + +void BaseDataStream::SetEndianness(std::endian endianness) +{ + mEndian = endianness; +} + +InputDataStream::InputDataStream(InputFileStream stream) + : mBackend{ std::move(stream) } +{ +} + +void InputDataStream::ReadBytes(size_t byteCount, std::byte* buffer) +{ + mBackend.ReadBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<std::byte*>(buffer)); +} + +void InputDataStream::ReadBytes(size_t byteCount, char* buffer) +{ + mBackend.ReadBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<std::byte*>(buffer)); +} + +void InputDataStream::ReadBytes(size_t byteCount, signed char* buffer) +{ + mBackend.ReadBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<std::byte*>(buffer)); +} + +void InputDataStream::ReadBytes(size_t byteCount, unsigned char* buffer) +{ + mBackend.ReadBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<std::byte*>(buffer)); +} + +void InputDataStream::Read(int8_t& n) +{ + // sizeof() of a reference type yields the size of the reference + mBackend.ReadBytes(sizeof(n), reinterpret_cast<std::byte*>(&n)); +} + +void InputDataStream::Read(int16_t& n) +{ + int16_t tmp; + mBackend.ReadBytes(sizeof(tmp), reinterpret_cast<std::byte*>(&tmp)); + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(tmp); + } else { + n = tmp; + } +} + +void InputDataStream::Read(int32_t& n) +{ + int32_t tmp; + mBackend.ReadBytes(sizeof(tmp), reinterpret_cast<std::byte*>(&tmp)); + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(tmp); + } else { + n = tmp; + } +} + +void InputDataStream::Read(int64_t& n) +{ + int64_t tmp; + mBackend.ReadBytes(sizeof(tmp), reinterpret_cast<std::byte*>(&tmp)); + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(tmp); + } else { + n = tmp; + } +} + +void InputDataStream::Read(uint8_t& n) +{ + mBackend.ReadBytes(sizeof(n), reinterpret_cast<std::byte*>(&n)); +} + +void InputDataStream::Read(uint16_t& n) +{ + uint16_t tmp; + mBackend.ReadBytes(sizeof(tmp), reinterpret_cast<std::byte*>(&tmp)); + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(tmp); + } else { + n = tmp; + } +} + +void InputDataStream::Read(uint32_t& n) +{ + uint32_t tmp; + mBackend.ReadBytes(sizeof(tmp), reinterpret_cast<std::byte*>(&tmp)); + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(tmp); + } else { + n = tmp; + } +} + +void InputDataStream::Read(uint64_t& n) +{ + uint64_t tmp; + mBackend.ReadBytes(sizeof(tmp), reinterpret_cast<std::byte*>(&tmp)); + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(tmp); + } else { + n = tmp; + } +} + +void InputDataStream::Read(float& n) +{ + uint32_t buffer; + Read(buffer); + + if (GetEndianness() != std::endian::native) { + buffer = ::ByteSwap(buffer); + } + + n = std::bit_cast<float>(buffer); +} + +void InputDataStream::Read(double& n) +{ + uint64_t buffer; + Read(buffer); + + if (GetEndianness() != std::endian::native) { + buffer = ::ByteSwap(buffer); + } + + n = std::bit_cast<double>(buffer); +} + +OutputDataStream::OutputDataStream(OutputFileStream stream) + : mBackend{ std::move(stream) } +{ +} + +void OutputDataStream::WriteBytes(size_t byteCount, const std::byte* buffer) +{ + mBackend.WriteBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<const std::byte*>(buffer)); +} + +void OutputDataStream::WriteBytes(size_t byteCount, const char* buffer) +{ + mBackend.WriteBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<const std::byte*>(buffer)); +} + +void OutputDataStream::WriteBytes(size_t byteCount, const signed char* buffer) +{ + mBackend.WriteBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<const std::byte*>(buffer)); +} + +void OutputDataStream::WriteBytes(size_t byteCount, const unsigned char* buffer) +{ + mBackend.WriteBytes(static_cast<std::streamsize>(byteCount), reinterpret_cast<const std::byte*>(buffer)); +} + +void OutputDataStream::Write(int8_t n) +{ + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(int16_t n) +{ + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(n); + } + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(int32_t n) +{ + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(n); + } + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(int64_t n) +{ + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(n); + } + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(uint8_t n) +{ + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(uint16_t n) +{ + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(n); + } + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(uint32_t n) +{ + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(n); + } + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(uint64_t n) +{ + if (GetEndianness() != std::endian::native) { + n = ::ByteSwap(n); + } + mBackend.WriteBytes(sizeof(n), reinterpret_cast<const std::byte*>(&n)); +} + +void OutputDataStream::Write(float n) +{ + auto buffer = std::bit_cast<uint32_t>(n); + if (GetEndianness() != std::endian::native) { + buffer = ::ByteSwap(buffer); + } + mBackend.WriteBytes(sizeof(buffer), reinterpret_cast<const std::byte*>(&buffer)); +} + +void OutputDataStream::Write(double n) +{ + auto buffer = std::bit_cast<uint64_t>(n); + if (GetEndianness() != std::endian::native) { + buffer = ::ByteSwap(buffer); + } + mBackend.WriteBytes(sizeof(buffer), reinterpret_cast<const std::byte*>(&buffer)); +} |