diff options
Diffstat (limited to 'core/src/Utils/IO')
-rw-r--r-- | core/src/Utils/IO/Archive.cpp | 57 | ||||
-rw-r--r-- | core/src/Utils/IO/Archive.hpp | 18 | ||||
-rw-r--r-- | core/src/Utils/IO/CstdioFile.cpp | 36 | ||||
-rw-r--r-- | core/src/Utils/IO/CstdioFile.hpp | 17 | ||||
-rw-r--r-- | core/src/Utils/IO/DataStream.cpp | 283 | ||||
-rw-r--r-- | core/src/Utils/IO/DataStream.hpp | 210 | ||||
-rw-r--r-- | core/src/Utils/IO/FileStream.cpp | 7 | ||||
-rw-r--r-- | core/src/Utils/IO/FileStream.hpp | 97 | ||||
-rw-r--r-- | core/src/Utils/IO/FileStream_Cstdio.inl | 126 | ||||
-rw-r--r-- | core/src/Utils/IO/FileStream_Custom.inl | 358 | ||||
-rw-r--r-- | core/src/Utils/IO/Helper.hpp | 43 | ||||
-rw-r--r-- | core/src/Utils/IO/StringIntegration.hpp | 37 | ||||
-rw-r--r-- | core/src/Utils/IO/TslArrayIntegration.hpp | 50 | ||||
-rw-r--r-- | core/src/Utils/IO/TslRobinIntegration.hpp | 78 | ||||
-rw-r--r-- | core/src/Utils/IO/UuidIntegration.hpp | 27 | ||||
-rw-r--r-- | core/src/Utils/IO/VectorIntegration.hpp | 42 | ||||
-rw-r--r-- | core/src/Utils/IO/fwd.hpp | 13 |
17 files changed, 0 insertions, 1499 deletions
diff --git a/core/src/Utils/IO/Archive.cpp b/core/src/Utils/IO/Archive.cpp deleted file mode 100644 index f6e7b27..0000000 --- a/core/src/Utils/IO/Archive.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "Archive.hpp" - -constexpr uint8_t kMagicNumbers[] = { 0x98, 0xd8, 0xa4, 0x65, 0x18, 0xa2, 0xd6, 0xa0 }; -constexpr size_t kMagicNumberCount = std::size(kMagicNumbers); - -constexpr uint8_t kByteOrderMark = []() { - switch (std::endian::native) { - case std::endian::little: return 0; - case std::endian::big: return 1; - } -}(); - -std::span<const uint8_t, 8> DataArchive::GetMagicNumbers() -{ - return std::span<const uint8_t, 8>{ kMagicNumbers }; -} - -std::optional<InputDataStream> DataArchive::LoadFile(const std::filesystem::path& path) -{ - InputFileStream fileStream(path); - fileStream.SetReadInSize(1024); - InputDataStream stream(std::move(fileStream)); - - uint8_t magicNumbers[kMagicNumberCount]; - stream.ReadBytes(kMagicNumberCount, magicNumbers); - - for (size_t i = 0; i < kMagicNumberCount; ++i) { - if (magicNumbers[i] != kMagicNumbers[i]) { - return {}; - } - } - - uint8_t byteOrderMark; - stream.Read(byteOrderMark); - - switch (byteOrderMark) { - case 0: stream.SetEndianness(std::endian::little); break; - case 1: stream.SetEndianness(std::endian::big); break; - default: std::abort(); - } - - return stream; -} - -std::optional<OutputDataStream> DataArchive::SaveFile(const std::filesystem::path& path) -{ - OutputFileStream fileStream(path, OutputFileStream::TruncateFile); - fileStream.SetMaxBufferSize(1024); - OutputDataStream stream(std::move(fileStream)); - - stream.WriteBytes(kMagicNumberCount, kMagicNumbers); - stream.Write(kByteOrderMark); - - stream.SetEndianness(std::endian::native); - - return stream; -} diff --git a/core/src/Utils/IO/Archive.hpp b/core/src/Utils/IO/Archive.hpp deleted file mode 100644 index 1bb8b59..0000000 --- a/core/src/Utils/IO/Archive.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" - -#include <cstdint> -#include <filesystem> -#include <optional> -#include <span> - -class DataArchive -{ -public: - static std::span<const uint8_t, 8> GetMagicNumbers(); - - // TODO more complete impl - static std::optional<InputDataStream> LoadFile(const std::filesystem::path& path); - static std::optional<OutputDataStream> SaveFile(const std::filesystem::path& path); -}; diff --git a/core/src/Utils/IO/CstdioFile.cpp b/core/src/Utils/IO/CstdioFile.cpp deleted file mode 100644 index 0f6378a..0000000 --- a/core/src/Utils/IO/CstdioFile.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "CstdioFile.hpp" - -#include "Utils/Macros.hpp" - -#pragma push_macro("MODE_STRING") -#undef MODE_STRING - -#if defined(_WIN32) -# define MODE_STRING(x) L##x -#else -# define MODE_STRING(x) x -#endif - -namespace CPLT_UNITY_ID { -auto GetModeString(FileUtils::IoMode mode) -{ - switch (mode) { - case FileUtils::IM_Read: return MODE_STRING("rb"); - case FileUtils::IM_WriteAppend: return MODE_STRING("ab"); - case FileUtils::IM_WriteTruncate: return MODE_STRING("wb"); - } - return MODE_STRING(""); -} -} // namespace CPLT_UNITY_ID - -#pragma pop_macro("MODE_STRING") - -FILE* FileUtils::OpenCstdioFile(const std::filesystem::path& path, IoMode mode) -{ -#ifdef _WIN32 - // std::filesystem::path::c_str() returns `const wchar_t*` under Windows, because NT uses UTF-16 natively - return _wfopen(path.c_str(), ::GetModeString(mode)); -#else - return fopen(path.c_str(), CPLT_UNITY_ID::GetModeString(mode)); -#endif -} diff --git a/core/src/Utils/IO/CstdioFile.hpp b/core/src/Utils/IO/CstdioFile.hpp deleted file mode 100644 index e863dd5..0000000 --- a/core/src/Utils/IO/CstdioFile.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include <cstdio> -#include <filesystem> - -namespace FileUtils { - -enum IoMode -{ - IM_Read, - IM_WriteAppend, - IM_WriteTruncate, -}; - -FILE* OpenCstdioFile(const std::filesystem::path& path, IoMode mode); - -} // namespace FileUtils diff --git a/core/src/Utils/IO/DataStream.cpp b/core/src/Utils/IO/DataStream.cpp deleted file mode 100644 index c0797e3..0000000 --- a/core/src/Utils/IO/DataStream.cpp +++ /dev/null @@ -1,283 +0,0 @@ -#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)); -} diff --git a/core/src/Utils/IO/DataStream.hpp b/core/src/Utils/IO/DataStream.hpp deleted file mode 100644 index c0891ac..0000000 --- a/core/src/Utils/IO/DataStream.hpp +++ /dev/null @@ -1,210 +0,0 @@ -#pragma once - -#include "FileStream.hpp" -#include "cplt_fwd.hpp" - -#include <bit> -#include <cstddef> -#include <cstdint> -#include <span> - -class BaseDataStream -{ -private: - std::endian mEndian = std::endian::big; - -public: - std::endian GetEndianness() const; - void SetEndianness(std::endian endianness); -}; - -class InputDataStream : public BaseDataStream -{ -private: - InputFileStream mBackend; - -public: - static constexpr bool IsSerializer() - { - return false; - } - - InputDataStream(InputFileStream stream); - - void ReadBytes(size_t byteCount, std::byte* buffer); - void ReadBytes(size_t byteCount, char* buffer); - void ReadBytes(size_t byteCount, signed char* buffer); - void ReadBytes(size_t byteCount, unsigned char* buffer); - - template <class TInserter> - void ReadBytes(size_t byteCount, TInserter&& inserter) - { - for (size_t i = 0; i < byteCount; ++i) { - uint8_t byte; - Read(byte); - - inserter = byte; - } - } - - void Read(int8_t& n); - void Read(int16_t& n); - void Read(int32_t& n); - void Read(int64_t& n); - - void Read(uint8_t& n); - void Read(uint16_t& n); - void Read(uint32_t& n); - void Read(uint64_t& n); - - void Read(float& n); - void Read(double& n); - - template <class TEnum> - requires std::is_enum_v<TEnum> - void ReadEnum(TEnum& e) - { - std::underlying_type_t<TEnum> n; - Read(n); - e = static_cast<TEnum>(e); - } - - template <class TObject> - void ReadObject(TObject& obj) - { - obj.ReadFromDataStream(*this); - } - - template <class TAdapter, class TObject> - void ReadObjectAdapted(TObject& obj) - { - TAdapter::ReadFromDataStream(*this, obj); - } - -public: - // Proxy functions for writing templated IO functions - - template <class T> - void Bytes(size_t byteCount, T* buffer) - { - ReadBytes(byteCount, buffer); - } - - template <class T> - void Value(T& t) - { - Read(t); - } - - template <class T> - void Enum(T& t) - { - ReadEnum(t); - } - - template <class T> - void Object(T& obj) - { - ReadObject(obj); - } - - template <class TAdapter, class TObject> - void ObjectAdapted(TObject& obj) - { - ReadObjectAdapted<TAdapter>(obj); - } -}; - -class OutputDataStream : public BaseDataStream -{ -private: - OutputFileStream mBackend; - -public: - static constexpr bool IsSerializer() - { - return true; - } - - OutputDataStream(OutputFileStream stream); - - void WriteBytes(size_t byteCount, const std::byte* buffer); - void WriteBytes(size_t byteCount, const char* buffer); - void WriteBytes(size_t byteCount, const signed char* buffer); - void WriteBytes(size_t byteCount, const unsigned char* buffer); - - template <class TIterator> - void WriteBytes(TIterator&& begin, TIterator&& end) - { - for (; begin != end; ++begin) { - uint8_t byte = *begin; - Write(byte); - } - } - - void Write(int8_t n); - void Write(int16_t n); - void Write(int32_t n); - void Write(int64_t n); - - void Write(uint8_t n); - void Write(uint16_t n); - void Write(uint32_t n); - void Write(uint64_t n); - - void Write(float n); - void Write(double n); - - template <class TEnum> - requires std::is_enum_v<TEnum> - void WriteEnum(TEnum e) - { - auto n = static_cast<std::underlying_type_t<TEnum>>(e); - Write(n); - } - - template <class TObject> - void WriteObject(const TObject& obj) - { - obj.WriteToDataStream(*this); - } - - template <class TAdapter, class TObject> - void WriteObjectAdapted(const TObject& obj) - { - TAdapter::WriteToDataStream(*this, obj); - } - -public: - // Proxy functions for writing templated IO functions - - template <class T> - void Bytes(size_t byteCount, T* buffer) - { - WriteBytes(byteCount, buffer); - } - - template <class T> - void Value(T t) - { - Write(t); - } - - template <class T> - void Enum(T t) - { - WriteEnum(t); - } - - template <class T> - void Object(T& obj) - { - WriteObject(obj); - } - - template <class TAdapter, class TObject> - void ObjectAdapted(TObject& obj) - { - WriteObjectAdapted<TAdapter>(obj); - } -}; diff --git a/core/src/Utils/IO/FileStream.cpp b/core/src/Utils/IO/FileStream.cpp deleted file mode 100644 index 8b83712..0000000 --- a/core/src/Utils/IO/FileStream.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "FileStream.hpp" - -#if defined(CPLT_FILESTREAM_USE_CSTDIO) -# include "FileStream_Cstdio.inl" -#else -# include "FileStream_Custom.inl" -#endif diff --git a/core/src/Utils/IO/FileStream.hpp b/core/src/Utils/IO/FileStream.hpp deleted file mode 100644 index 453ddbe..0000000 --- a/core/src/Utils/IO/FileStream.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -#include <cstddef> -#include <cstdint> -#include <filesystem> -#include <memory> - -// TODO switch to custom when unit tests are ready and bugs are fixed -#define CPLT_FILESTREAM_USE_CSTDIO - -struct IoResult -{ - enum ErrorKind - { - ERR_None, - ERR_PermissionDenied, - ERR_UnexpectedEof, - ERR_Unsupported, - ERR_OutOfSpace, - ERR_Other, - }; - - ErrorKind Error; - uint32_t SystemError; - size_t BytesMoved; -}; - -class InputFileStream -{ -private: -#if defined(CPLT_FILESTREAM_USE_CSTDIO) - FILE* mFile; -#else - alignas(void*) char mOsFileHandle[sizeof(void*)]; - - // mBuffer is always mReadInSize size - std::unique_ptr<std::byte[]> mBuffer; - int mReadInSize = 1024; - - int mFirstByteIdx = 0; - int mAvailableBytes = 0; - - bool mEof = false; -#endif - -public: - InputFileStream(const std::filesystem::path& path); - ~InputFileStream(); - - InputFileStream(const InputFileStream&) = delete; - InputFileStream& operator=(const InputFileStream&) = delete; - InputFileStream(InputFileStream&&); - InputFileStream& operator=(InputFileStream&&); - - int GetReadInSize() const; - void SetReadInSize(int size); - - bool IsEof() const; - - IoResult ReadBytes(size_t bufferLength, std::byte* buffer); -}; - -class OutputFileStream -{ -public: - enum WriteMode - { - AppendFile, - TruncateFile, - }; - -private: -#if defined(CPLT_FILESTREAM_USE_CSTDIO) - FILE* mFile; -#else - alignas(void*) char mOsFileHandle[sizeof(void*)]; - std::unique_ptr<std::byte[]> mBuffer; - int mMaxBufferSize = 1024; - int mCurrentBufferSize = 0; -#endif - -public: - OutputFileStream(const std::filesystem::path& path, WriteMode mode); - ~OutputFileStream(); - - OutputFileStream(const OutputFileStream&) = delete; - OutputFileStream& operator=(const OutputFileStream&) = delete; - OutputFileStream(OutputFileStream&&); - OutputFileStream& operator=(OutputFileStream&&); - - int GetMaxBufferSize() const; - void SetMaxBufferSize(int maxSize); - - IoResult WriteBytes(size_t bufferLength, const std::byte* buffer); - - void FlushBuffer(); -}; diff --git a/core/src/Utils/IO/FileStream_Cstdio.inl b/core/src/Utils/IO/FileStream_Cstdio.inl deleted file mode 100644 index ee55681..0000000 --- a/core/src/Utils/IO/FileStream_Cstdio.inl +++ /dev/null @@ -1,126 +0,0 @@ -// Note: included by FileStream.cpp conditionally, not compiled separately -#include "FileStream.hpp" - -#include "Utils/IO/CstdioFile.hpp" - -#include <cstdio> -#include <filesystem> - -namespace fs = std::filesystem; - -InputFileStream::InputFileStream(const fs::path& path) - : mFile{ FileUtils::OpenCstdioFile(path, FileUtils::IM_Read) } -{ -} - -InputFileStream::~InputFileStream() -{ - if (mFile) { - std::fclose(mFile); - } -} - -InputFileStream::InputFileStream(InputFileStream&& that) - : mFile{ that.mFile } -{ - that.mFile = nullptr; -} - -InputFileStream& InputFileStream::operator=(InputFileStream&& that) -{ - if (this == &that) return *this; - - if (mFile) { - std::fclose(mFile); - } - mFile = that.mFile; - that.mFile = nullptr; - - return *this; -} - -OutputFileStream::OutputFileStream(const fs::path& path, WriteMode mode) -{ - switch (mode) { - case AppendFile: mFile = FileUtils::OpenCstdioFile(path, FileUtils::IM_WriteAppend); break; - case TruncateFile: mFile = FileUtils::OpenCstdioFile(path, FileUtils::IM_WriteTruncate); break; - } -} - -OutputFileStream::~OutputFileStream() -{ - if (mFile) { - std::fclose(mFile); - } -} - -OutputFileStream::OutputFileStream(OutputFileStream&& that) - : mFile{ that.mFile } -{ - that.mFile = nullptr; -} - -OutputFileStream& OutputFileStream::operator=(OutputFileStream&& that) -{ - if (this == &that) return *this; - - if (mFile) { - std::fclose(mFile); - } - mFile = that.mFile; - that.mFile = nullptr; - - return *this; -} - -int InputFileStream::GetReadInSize() const -{ - return 0; -} - -void InputFileStream::SetReadInSize(int size) -{ - // No-op -} - -bool InputFileStream::IsEof() const -{ - return std::feof(mFile); -} - -IoResult InputFileStream::ReadBytes(size_t bufferLength, std::byte* buffer) -{ - auto bytesRead = std::fread(buffer, 1, bufferLength, mFile); - - return { - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesRead, - }; -} - -int OutputFileStream::GetMaxBufferSize() const -{ - return 0; -} - -void OutputFileStream::SetMaxBufferSize(int maxSize) -{ - // No-op -} - -IoResult OutputFileStream::WriteBytes(size_t bufferLength, const std::byte* buffer) -{ - auto bytesWritten = std::fwrite(buffer, 1, bufferLength, mFile); - - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesWritten, - }; -} - -void OutputFileStream::FlushBuffer() -{ - // No-op -} diff --git a/core/src/Utils/IO/FileStream_Custom.inl b/core/src/Utils/IO/FileStream_Custom.inl deleted file mode 100644 index 004dd01..0000000 --- a/core/src/Utils/IO/FileStream_Custom.inl +++ /dev/null @@ -1,358 +0,0 @@ -// Note: included by FileStream.cpp conditionally, not compiled separately -#include "FileStream.hpp" - -#include <cstring> -#include <filesystem> -#include <iostream> - -namespace fs = std::filesystem; - -#if defined(_WIN32) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <Windows.h> - -InputFileStream::InputFileStream(const fs::path& path) - : mOsFileHandle{ 0 } -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - - *handle = CreateFileW( - path.c_str(), // fs::path::c_str() returns a wide string on Windows - GENERIC_READ, - /* No sharing */ 0, - /* Use default security*/ nullptr, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - /* No attribute template */ nullptr); - - // TODO handle error -} - -InputFileStream::~InputFileStream() -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - CloseHandle(*handle); -} - -OutputFileStream::OutputFileStream(const fs::path& path, WriteMode mode) - : mOsFileHandle{ 0 } -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - - DWORD creationDisposition; - switch (mode) { - case AppendFile: creationDisposition = OPEN_ALWAYS; break; - case TruncateFile: creationDisposition = CREATE_ALWAYS; break; - } - - *handle = CreateFileW( - path.c_str(), - GENERIC_WRITE, - /* No sharing */ 0, - /* Use default security*/ nullptr, - creationDisposition, - FILE_ATTRIBUTE_NORMAL, - /* No attribute template */ nullptr); - - // TODO handle error -} - -OutputFileStream::~OutputFileStream() -{ - auto handle = reinterpret_cast<HANDLE*>(mOsFileHandle); - CloseHandle(*handle); -} - -static IoResult::ErrorKind MapErrorCodeToIoResult(DWORD error) -{ - switch (error) { - // TODO - - default: - std::cerr << "Unimplemented win32 error code " << error << ", report bug immediately.\n"; - std::abort(); - } -} - -static IoResult ReadBytesDirect(HANDLE hFile, size_t byteCount, std::byte* bytes) -{ - DWORD bytesRead; - BOOL result = ReadFile(hFile, bytes, byteCount, &bytesRead, nullptr); - - if (result) { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesRead, - }; - } else { - DWORD errorCode = GetLastError(); - return IoResult{ - .Error = ::MapErrorCodeToIoResult(errorCode), - .SystemError = errorCode, - .BytesMoved = bytesRead, - }; - } -} - -static IoResult WriteBytesDirect(HANDLE hFile, size_t byteCount, const std::byte* bytes) -{ - DWORD bytesWritten; - BOOL result = WriteFile(hFile, bytes, byteCount, &bytesWritten, nullptr); - - if (result) { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesWritten, - }; - } else { - DWORD errorCode = GetLastError(); - return IoResult{ - .Error = ::MapErrorCodeToIoResult(errorCode), - .SystemError = errorCode, - .BytesMoved = bytesWritten, - }; - } -} - -#elif defined(__APPLE__) || defined(__linux__) -# include <fcntl.h> -# include <sys/stat.h> -# include <sys/types.h> -# include <unistd.h> - -InputFileStream::InputFileStream(const fs::path& path) - : mOsFileHandle{ 0 } -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - *fd = open(path.c_str(), O_RDONLY); -} - -InputFileStream::~InputFileStream() -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - close(*fd); -} - -OutputFileStream::OutputFileStream(const fs::path& path, WriteMode mode) - : mOsFileHandle{ 0 } -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - - int flags = O_WRONLY | O_CREAT; - switch (mode) { - case AppendFile: flags |= O_APPEND; break; - case TruncateFile: flags |= O_TRUNC; break; - } - - *fd = open(path.c_str(), flags, 0644); -} - -OutputFileStream::~OutputFileStream() -{ - auto fd = reinterpret_cast<int*>(mOsFileHandle); - close(*fd); -} - -static IoResult::ErrorKind MapErrnoToIoResult(int err) -{ - switch (err) { - // TODO - case EFAULT: return IoResult::ERR_UnexpectedEof; - case EPERM: return IoResult::ERR_PermissionDenied; - case ENOSPC: return IoResult::ERR_OutOfSpace; - case EIO: return IoResult::ERR_Other; - - default: - std::cerr << "Unimplemented POSIX errno " << err << ", report bug immediately.\n"; - std::abort(); - } -} - -static IoResult ReadBytesDirect(const char* osFileHandle, size_t byteCount, std::byte* bytes) -{ - int fd = *reinterpret_cast<const int*>(osFileHandle); - int status = read(fd, bytes, byteCount); - - if (status == -1) { - int err = errno; - return IoResult{ - .Error = ::MapErrnoToIoResult(err), - .SystemError = (uint32_t)err, - .BytesMoved = 0, - }; - } else { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = (size_t)status, // Equal to number of bytes read - }; - } -} - -static IoResult WriteBytesDirect(const char* osFileHandle, size_t byteCount, const std::byte* bytes) -{ - int fd = *reinterpret_cast<const int*>(osFileHandle); - int status = write(fd, bytes, byteCount); - - if (status == -1) { - int err = errno; - return IoResult{ - .Error = ::MapErrnoToIoResult(err), - .SystemError = (uint32_t)err, - .BytesMoved = 0, - }; - } else { - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = (size_t)status, // Equal to number of bytes read - }; - } -} - -#else -# error "Unsupported target platform." -#endif - -int InputFileStream::GetReadInSize() const -{ - return mReadInSize; -} - -void InputFileStream::SetReadInSize(int size) -{ - if (size > mReadInSize) { - mReadInSize = size; - mBuffer = std::make_unique<std::byte[]>(size); - } -} - -bool InputFileStream::IsEof() const -{ - return mEof; -} - -IoResult InputFileStream::ReadBytes(size_t bufferLength, std::byte* buffer) -{ - // TODO reduce duplicated code - - auto bytesMoved = std::min<size_t>(mAvailableBytes, bufferLength); - - // On first call after construction, mFirstByteIdx will equal to mReadInSize, i.e. bytesAvailable == 0 - // and this call to std::memcpy will be no-op - std::memcpy(buffer, &mBuffer[mFirstByteIdx], bytesMoved); - mFirstByteIdx += (int)bytesMoved; - mAvailableBytes -= (int)bytesMoved; - buffer += bytesMoved; - - size_t bytesLeft = bufferLength - bytesMoved; - if (bytesLeft > mReadInSize) { - // Our buffer can't handle rest of the request, just skip the buffering step - - // Read rest of the data into buffer - { - auto result = ::ReadBytesDirect(mOsFileHandle, bytesLeft, buffer); - bytesMoved += result.BytesMoved; - - if (result.Error == IoResult::ERR_None) { - if (result.BytesMoved < mReadInSize) { - mEof = true; - } - } else { - goto end; - } - } - - // Refill our buffer - { - auto result = ::ReadBytesDirect(mOsFileHandle, mReadInSize, mBuffer.get()); - mFirstByteIdx = 0; - mAvailableBytes = (int)result.BytesMoved; - - if (result.Error == IoResult::ERR_None) { - if (result.BytesMoved < mReadInSize) { - mEof = true; - } - } else { - goto end; - } - } - } else if (bytesLeft > 0) { - // Our buffer can handle rest of the request, first buffer than supply the requested data - - // Refill our buffer - { - auto result = ::ReadBytesDirect(mOsFileHandle, mReadInSize, mBuffer.get()); - mFirstByteIdx = 0; - mAvailableBytes = (int)result.BytesMoved; - - if (result.Error == IoResult::ERR_None) { - if (result.BytesMoved < mReadInSize) { - mEof = true; - } - } else { - goto end; - } - } - - // Copy data into buffer - { - std::memcpy(buffer, &mBuffer[mFirstByteIdx], bytesLeft); - mFirstByteIdx += (int)bytesLeft; - bytesMoved += bytesLeft; - buffer += bytesLeft; - } - } else { - // Request completed already - } - -end: - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bytesMoved, - }; -} - -int OutputFileStream::GetMaxBufferSize() const -{ - return mMaxBufferSize; -} - -void OutputFileStream::SetMaxBufferSize(int maxSize) -{ - FlushBuffer(); - if (maxSize > mMaxBufferSize) { - mMaxBufferSize = maxSize; - mBuffer = std::make_unique<std::byte[]>(maxSize); - } -} - -IoResult OutputFileStream::WriteBytes(size_t bufferLength, const std::byte* buffer) -{ - if (bufferLength + mCurrentBufferSize > mMaxBufferSize) { - FlushBuffer(); - - if (bufferLength > mMaxBufferSize) { - return ::WriteBytesDirect(mOsFileHandle, bufferLength, buffer); - } - } - - std::memcpy(mBuffer.get() + mCurrentBufferSize, buffer, bufferLength); - mCurrentBufferSize += (int)bufferLength; - - return IoResult{ - .Error = IoResult::ERR_None, - .SystemError = 0, - .BytesMoved = bufferLength, - }; -} - -void OutputFileStream::FlushBuffer() -{ - ::WriteBytesDirect(mOsFileHandle, mCurrentBufferSize, mBuffer.get()); - mCurrentBufferSize = 0; -} diff --git a/core/src/Utils/IO/Helper.hpp b/core/src/Utils/IO/Helper.hpp deleted file mode 100644 index ebd47a7..0000000 --- a/core/src/Utils/IO/Helper.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" - -namespace DataStreamAdapters { - -/// Helper to invoke either Read() or ReadObject(). -/// This is intended for writing IO adapters, users that's writing IO logic shouldn't using this - it increases compile time while reducing readability. -template <class TAdapter, class T> -void ReadHelper(InputDataStream& stream, T& t) -{ - if constexpr (!std::is_same_v<TAdapter, void>) { - stream.ReadObjectAdapted<TAdapter>(t); - } else if constexpr (requires(T tt, InputDataStream ss) { ss.Read(tt); }) { - stream.Read(t); - } else if constexpr (requires(T tt, InputDataStream ss) { ss.ReadEnum(tt); }) { - stream.ReadEnum(t); - } else if constexpr (requires(T tt, InputDataStream ss) { ss.ReadObject(tt); }) { - stream.ReadObject(t); - } else { - static_assert(false && sizeof(T), "This type is neither a 'value' nor an 'object'."); - } -} - -/// Helper to invoke either Write() or WriteObject(). -/// This is intended for writing IO adapters, users that's writing IO logic shouldn't using this - it increases compile time while reducing readability. -template <class TAdapter, class T> -void WriteHelper(OutputDataStream& stream, T& t) -{ - if constexpr (!std::is_same_v<TAdapter, void>) { - stream.WriteObjectAdapted<TAdapter>(t); - } else if constexpr (requires(T tt, OutputDataStream ss) { ss.Write(tt); }) { - stream.Write(t); - } else if constexpr (requires(T tt, OutputDataStream ss) { ss.WriteEnum(tt); }) { - stream.WriteEnum(t); - } else if constexpr (requires(T tt, OutputDataStream ss) { ss.WriteObject(tt); }) { - stream.WriteObject(t); - } else { - static_assert(false && sizeof(T), "This type is neither a 'value' nor an 'object'."); - } -} - -} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/StringIntegration.hpp b/core/src/Utils/IO/StringIntegration.hpp deleted file mode 100644 index 536cb83..0000000 --- a/core/src/Utils/IO/StringIntegration.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" - -#include <iterator> -#include <string> -#include <string_view> - -namespace DataStreamAdapters { -struct String -{ - static void ReadFromDataStream(InputDataStream& stream, std::string& str) - { - uint64_t size; - stream.Read(size); - - str = {}; - str.reserve(size); - stream.ReadBytes(size, std::back_inserter(str)); - } - - static void WriteToDataStream(OutputDataStream& stream, const std::string& str) - { - stream.Write((uint64_t)str.size()); - stream.WriteBytes(str.size(), str.data()); - } -}; - -struct StringView -{ - static void WriteToDataStream(OutputDataStream& stream, const std::string_view& str) - { - stream.Write((uint64_t)str.size()); - stream.WriteBytes(str.size(), str.data()); - } -}; -} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/TslArrayIntegration.hpp b/core/src/Utils/IO/TslArrayIntegration.hpp deleted file mode 100644 index af1197c..0000000 --- a/core/src/Utils/IO/TslArrayIntegration.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" -#include "Utils/IO/Helper.hpp" -#include "Utils/IO/StringIntegration.hpp" - -#include <tsl/array_map.h> -#include <tsl/array_set.h> -#include <string> -#include <type_traits> - -// TODO support custom key types - -namespace DataStreamAdapters { -template <class TAdapter = void> -struct TslArrayMap -{ - template <class TValue> - static void ReadFromDataStream(InputDataStream& stream, tsl::array_map<char, TValue>& map) - { - static_assert(std::is_default_constructible_v<TValue>); - static_assert(std::is_move_constructible_v<TValue>); - - uint64_t size; - stream.Read(size); - map.reserve(size); - - for (uint64_t i = 0; i < size; ++i) { - std::string key; - stream.ReadObjectAdapted<DataStreamAdapters::String>(key); - - TValue value; - ReadHelper<TAdapter>(stream, value); - - map.insert(key, std::move(value)); - } - } - - template <class TValue> - static void WriteToDataStream(OutputDataStream& stream, const tsl::array_map<char, TValue>& map) - { - stream.Write((uint64_t)map.size()); - - for (auto it = map.begin(); it != map.end(); ++it) { - stream.WriteObjectAdapted<DataStreamAdapters::StringView>(it.key_sv()); - WriteHelper<TAdapter>(stream, it.value()); - } - } -}; -} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/TslRobinIntegration.hpp b/core/src/Utils/IO/TslRobinIntegration.hpp deleted file mode 100644 index 50775fe..0000000 --- a/core/src/Utils/IO/TslRobinIntegration.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" -#include "Utils/IO/Helper.hpp" - -#include <tsl/robin_map.h> -#include <tsl/robin_set.h> -#include <type_traits> - -namespace DataStreamAdapters { -template <class TKeyAdapter = void, class TValueAdapter = void> -struct TslRobinMap -{ - template <class TKey, class TValue> - static void ReadFromDataStream(InputDataStream& stream, tsl::robin_map<TKey, TValue>& map) - { - static_assert(std::is_default_constructible_v<TValue>); - static_assert(std::is_move_constructible_v<TValue>); - - uint64_t size; - stream.Read(size); - map.reserve(size); - - for (uint64_t i = 0; i < size; ++i) { - TKey key; - ReadHelper<TKeyAdapter>(stream, key); - - TValue value; - ReadHelper<TValueAdapter>(stream, value); - - map.insert(std::move(key), std::move(value)); - } - } - - template <class TKey, class TValue> - static void WriteToDataStream(OutputDataStream& stream, const tsl::robin_map<TKey, TValue>& map) - { - stream.Write((uint64_t)map.size()); - - for (auto it = map.begin(); it != map.end(); ++it) { - WriteHelper<TKeyAdapter>(stream, it.key()); - WriteHelper<TValueAdapter>(stream, it.value()); - } - } -}; - -template <class TAdapter = void> -struct TslRobinSet -{ - template <class TElement> - static void ReadFromDataStream(InputDataStream& stream, tsl::robin_set<TElement>& set) - { - static_assert(std::is_default_constructible_v<TElement>); - static_assert(std::is_move_constructible_v<TElement>); - - uint64_t size; - stream.Read(size); - set.reserve(size); - - for (uint64_t i = 0; i < size; ++i) { - TElement element; - ReadHelper<TAdapter>(stream, element); - - set.insert(std::move(element)); - } - } - - template <class TElement> - static void WriteToDataStream(OutputDataStream& stream, const tsl::robin_set<TElement>& set) - { - stream.Write((uint64_t)set.size()); - - for (auto& element : set) { - WriteHelper<TAdapter>(stream, element); - } - } -}; -} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/UuidIntegration.hpp b/core/src/Utils/IO/UuidIntegration.hpp deleted file mode 100644 index d028c50..0000000 --- a/core/src/Utils/IO/UuidIntegration.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" -#include "Utils/UUID.hpp" - -#include <cstddef> -#include <cstdint> -#include <iterator> - -namespace DataStreamAdapters { -struct Uuid -{ - static void ReadFromDataStream(InputDataStream& stream, uuids::uuid& uuid) - { - uint8_t buffer[16]; - stream.ReadBytes(16, buffer); - - uuid = uuids::uuid(gsl::span<uint8_t, 16>{ buffer }); - } - - static void WriteToDataStream(OutputDataStream& stream, const uuids::uuid& uuid) - { - auto gslSpan = uuid.as_bytes(); - stream.WriteBytes(gslSpan.size(), gslSpan.data()); - } -}; -} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/VectorIntegration.hpp b/core/src/Utils/IO/VectorIntegration.hpp deleted file mode 100644 index 3689505..0000000 --- a/core/src/Utils/IO/VectorIntegration.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "Utils/IO/DataStream.hpp" -#include "Utils/IO/Helper.hpp" - -#include <type_traits> -#include <vector> - -namespace DataStreamAdapters { -template <class TAdapter = void> -struct Vector -{ - template <class TElement> - static void ReadFromDataStream(InputDataStream& stream, std::vector<TElement>& vec) - { - static_assert(std::is_default_constructible_v<TElement>); - static_assert(std::is_move_constructible_v<TElement>); - - uint64_t size; - stream.Read(size); - - vec.clear(); - vec.reserve(size); - - for (uint64_t i = 0; i < size; ++i) { - TElement element; - ReadHelper<TAdapter>(stream, element); - - vec.push_back(std::move(element)); - } - } - - template <class TElement> - static void WriteToDataStream(OutputDataStream& stream, const std::vector<TElement>& vec) - { - stream.Write((uint64_t)vec.size()); - for (auto& element : vec) { - WriteHelper<TAdapter>(stream, element); - } - } -}; -} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/fwd.hpp b/core/src/Utils/IO/fwd.hpp deleted file mode 100644 index 9f1492b..0000000 --- a/core/src/Utils/IO/fwd.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// Archive.hpp -class DataArchive; - -// BaseDataStream.hpp -class BaseDataStream; -class InputDataStream; -class OutputDataStream; - -// FileStream.hpp -class InputFileStream; -class OutputFileStream; |