aboutsummaryrefslogtreecommitdiff
path: root/core/src/Utils
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-27 18:27:13 -0700
committerrtk0c <[email protected]>2022-06-27 18:27:13 -0700
commit8f0dda5eab181b0f14f2652b4e984aaaae3f258c (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/src/Utils
parentfad6a88a13ab1f888ab25ad0aae19c1d63aa0623 (diff)
Start from a clean slate
Diffstat (limited to 'core/src/Utils')
-rw-r--r--core/src/Utils/Color.hpp202
-rw-r--r--core/src/Utils/Hash.hpp15
-rw-r--r--core/src/Utils/I18n.hpp10
-rw-r--r--core/src/Utils/IO/Archive.cpp57
-rw-r--r--core/src/Utils/IO/Archive.hpp18
-rw-r--r--core/src/Utils/IO/CstdioFile.cpp36
-rw-r--r--core/src/Utils/IO/CstdioFile.hpp17
-rw-r--r--core/src/Utils/IO/DataStream.cpp283
-rw-r--r--core/src/Utils/IO/DataStream.hpp210
-rw-r--r--core/src/Utils/IO/FileStream.cpp7
-rw-r--r--core/src/Utils/IO/FileStream.hpp97
-rw-r--r--core/src/Utils/IO/FileStream_Cstdio.inl126
-rw-r--r--core/src/Utils/IO/FileStream_Custom.inl358
-rw-r--r--core/src/Utils/IO/Helper.hpp43
-rw-r--r--core/src/Utils/IO/StringIntegration.hpp37
-rw-r--r--core/src/Utils/IO/TslArrayIntegration.hpp50
-rw-r--r--core/src/Utils/IO/TslRobinIntegration.hpp78
-rw-r--r--core/src/Utils/IO/UuidIntegration.hpp27
-rw-r--r--core/src/Utils/IO/VectorIntegration.hpp42
-rw-r--r--core/src/Utils/IO/fwd.hpp13
-rw-r--r--core/src/Utils/Macros.hpp13
-rw-r--r--core/src/Utils/Math.hpp11
-rw-r--r--core/src/Utils/RTTI.hpp49
-rw-r--r--core/src/Utils/ScopeGuard.hpp39
-rw-r--r--core/src/Utils/Sigslot.cpp233
-rw-r--r--core/src/Utils/Sigslot.hpp165
-rw-r--r--core/src/Utils/Size.hpp65
-rw-r--r--core/src/Utils/StandardDirectories.cpp78
-rw-r--r--core/src/Utils/StandardDirectories.hpp10
-rw-r--r--core/src/Utils/Time.cpp29
-rw-r--r--core/src/Utils/Time.hpp11
-rw-r--r--core/src/Utils/UUID.hpp5
-rw-r--r--core/src/Utils/Variant.hpp33
-rw-r--r--core/src/Utils/Vector.hpp144
-rw-r--r--core/src/Utils/VectorHash.hpp46
-rw-r--r--core/src/Utils/fwd.hpp17
36 files changed, 0 insertions, 2674 deletions
diff --git a/core/src/Utils/Color.hpp b/core/src/Utils/Color.hpp
deleted file mode 100644
index 19227e0..0000000
--- a/core/src/Utils/Color.hpp
+++ /dev/null
@@ -1,202 +0,0 @@
-#pragma once
-
-#include "Utils/Math.hpp"
-#include "Utils/Vector.hpp"
-#include "Utils/fwd.hpp"
-
-#include <imgui.h>
-#include <algorithm>
-#include <cstdint>
-#include <limits>
-
-class RgbaColor
-{
-public:
- uint8_t r;
- uint8_t g;
- uint8_t b;
- uint8_t a;
-
-public:
- constexpr RgbaColor() noexcept
- : r{ 255 }
- , g{ 255 }
- , b{ 255 }
- , a{ 255 }
- {
- }
-
- constexpr RgbaColor(float r, float g, float b, float a = 1.0f) noexcept
- : r{ static_cast<uint8_t>(r * 255.0f) }
- , g{ static_cast<uint8_t>(g * 255.0f) }
- , b{ static_cast<uint8_t>(b * 255.0f) }
- , a{ static_cast<uint8_t>(a * 255.0f) }
- {
- }
-
- constexpr RgbaColor(int r, int g, int b, int a = 255) noexcept
- : r{ static_cast<uint8_t>(r & 0xFF) }
- , g{ static_cast<uint8_t>(g & 0xFF) }
- , b{ static_cast<uint8_t>(b & 0xFF) }
- , a{ static_cast<uint8_t>(a & 0xFF) }
- {
- }
-
- constexpr RgbaColor(uint32_t rgba) noexcept
- : r{ static_cast<uint8_t>((rgba >> 0) & 0xFF) }
- , g{ static_cast<uint8_t>((rgba >> 8) & 0xFF) }
- , b{ static_cast<uint8_t>((rgba >> 16) & 0xFF) }
- , a{ static_cast<uint8_t>((rgba >> 24) & 0xFF) }
- {
- }
-
- constexpr uint32_t GetScalar() const noexcept
- {
- uint32_t res = 0;
- res |= r << 24;
- res |= g << 16;
- res |= b << 8;
- res |= a;
- return res;
- }
-
- constexpr void SetScalar(uint32_t scalar) noexcept
- {
- r = (scalar >> 0) & 0xFF;
- g = (scalar >> 8) & 0xFF;
- b = (scalar >> 16) & 0xFF;
- a = (scalar >> 24) & 0xFF;
- }
-
- constexpr float GetNormalizedRed() const noexcept
- {
- return r / 255.0f;
- }
-
- constexpr float GetNormalizedGreen() const noexcept
- {
- return g / 255.0f;
- }
-
- constexpr float GetNormalizedBlue() const noexcept
- {
- return b / 255.0f;
- }
-
- constexpr float GetNormalizedAlpha() const noexcept
- {
- return a / 255.0f;
- }
-
- constexpr Vec4i AsVec4i() const noexcept
- {
- return Vec4i{ r, g, b, a };
- }
-
- constexpr Vec4f AsVec4f() const noexcept
- {
- return Vec4f{
- GetNormalizedRed(),
- GetNormalizedGreen(),
- GetNormalizedBlue(),
- GetNormalizedAlpha(),
- };
- }
-
- ImVec4 AsImVec() const
- {
- auto v = AsVec4f();
- return ImVec4{ v.x, v.y, v.z, v.w };
- }
-
- ImColor AsImColor() const
- {
- auto v = AsVec4f();
- return ImColor{ v.x, v.y, v.z, v.w };
- }
-
- ImU32 AsImU32() const
- {
- ImU32 res;
- res |= r << IM_COL32_R_SHIFT;
- res |= g << IM_COL32_G_SHIFT;
- res |= b << IM_COL32_B_SHIFT;
- res |= a << IM_COL32_A_SHIFT;
- return res;
- }
-
- constexpr void SetVec(const Vec4f& vec) noexcept
- {
- r = (uint8_t)(vec.x * 255.0f);
- g = (uint8_t)(vec.y * 255.0f);
- b = (uint8_t)(vec.z * 255.0f);
- a = (uint8_t)(vec.w * 255.0f);
- }
-
- // Forward declaring because cyclic reference between RgbaColor and HsvColor
- constexpr HsvColor ToHsv() const noexcept;
-
- friend constexpr bool operator==(const RgbaColor&, const RgbaColor&) noexcept = default;
-};
-
-class HsvColor
-{
-public:
- float h;
- float s;
- float v;
- float a;
-
-public:
- constexpr HsvColor() noexcept
- : h{ 0.0f }
- , s{ 0.0f }
- , v{ 1.0f }
- , a{ 1.0f }
- {
- }
-
- constexpr HsvColor(float h, float s, float v, float a) noexcept
- : h{ h }
- , s{ s }
- , v{ v }
- , a{ a }
- {
- }
-
- // Forward declaring because cyclic reference between RgbaColor and HsvColor
- constexpr RgbaColor ToRgba() const noexcept;
-};
-
-constexpr HsvColor RgbaColor::ToHsv() const noexcept
-{
- float fr = GetNormalizedRed();
- float fg = GetNormalizedBlue();
- float fb = GetNormalizedGreen();
- float fa = GetNormalizedAlpha();
-
- auto p = fg < fb ? Vec4f{ fb, fg, -1, 2.0f / 3.0f } : Vec4f{ fg, fb, 0, -1.0f / 3.0f };
- auto q = fr < p.x ? Vec4f{ p.x, p.y, p.w, fr } : Vec4f{ fr, p.y, p.z, p.x };
- float c = q.x - std::min(q.w, q.y);
- float h = MathUtils::Abs((q.w - q.y) / (6 * c + std::numeric_limits<float>::epsilon()) + q.z);
-
- Vec3f hcv{ h, c, q.x };
- float s = hcv.y / (hcv.z + std::numeric_limits<float>::epsilon());
- return HsvColor(hcv.x, s, hcv.z, fa);
-}
-
-constexpr RgbaColor HsvColor::ToRgba() const noexcept
-{
- float r = MathUtils::Abs(h * 6 - 3) - 1;
- float g = 2 - MathUtils::Abs(h * 6 - 2);
- float b = 2 - MathUtils::Abs(h * 6 - 4);
-
- auto rgb = Vec3f{
- std::clamp(r, 0.0f, 1.0f),
- std::clamp(g, 0.0f, 1.0f),
- std::clamp(b, 0.0f, 1.0f),
- };
- auto vc = (rgb - Vec3f{ 0, 0, 0 }) * s + Vec3f{ 1, 1, 1 } * v;
-
- return RgbaColor(vc.x, vc.y, vc.z, a);
-}
diff --git a/core/src/Utils/Hash.hpp b/core/src/Utils/Hash.hpp
deleted file mode 100644
index cf7713a..0000000
--- a/core/src/Utils/Hash.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-#include <cstddef>
-#include <functional>
-
-namespace HashUtils {
-
-template <class T>
-void Combine(size_t& seed, const T& v)
-{
- std::hash<T> hasher;
- seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-}
-
-} // namespace HashUtils
diff --git a/core/src/Utils/I18n.hpp b/core/src/Utils/I18n.hpp
deleted file mode 100644
index e9eaac9..0000000
--- a/core/src/Utils/I18n.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-#include "Utils/Macros.hpp"
-
-#if !defined(TARGET_LOCALE)
-# define I18N_TEXT(defaultText, name) defaultText
-#else
-# include TARGET_LOCALE_FILE
-# define I18N_TEXT(defaultText, name) name
-#endif
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;
diff --git a/core/src/Utils/Macros.hpp b/core/src/Utils/Macros.hpp
deleted file mode 100644
index 6958ed1..0000000
--- a/core/src/Utils/Macros.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#define STRINGIFY_IMPL(text) #text
-#define STRINGIFY(text) STRINGIFY_IMPL(text)
-
-#define CONCAT_IMPL(a, b) a##b
-#define CONCAT(a, b) CONCAT_IMPL(a, b)
-#define CONCAT_3(a, b, c) CONCAT(a, CONCAT(b, c))
-#define CONCAT_4(a, b, c, d) CONCAT(CONCAT(a, b), CONCAT(c, d))
-
-#define UNIQUE_NAME(prefix) CONCAT(prefix, __COUNTER__)
-#define UNIQUE_NAME_LINE(prefix) CONCAT(prefix, __LINE__)
-#define DISCARD UNIQUE_NAME(_discard)
diff --git a/core/src/Utils/Math.hpp b/core/src/Utils/Math.hpp
deleted file mode 100644
index da53da2..0000000
--- a/core/src/Utils/Math.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-namespace MathUtils {
-
-template <class T>
-constexpr T Abs(T t)
-{
- return t < 0 ? -t : t;
-}
-
-} // namespace MathUtils
diff --git a/core/src/Utils/RTTI.hpp b/core/src/Utils/RTTI.hpp
deleted file mode 100644
index 86b1e2c..0000000
--- a/core/src/Utils/RTTI.hpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-
-#include <cassert>
-
-template <class T, class TBase>
-bool is_a(TBase* t)
-{
- assert(t != nullptr);
- return T::IsInstance(t);
-}
-
-template <class T, class TBase>
-bool is_a_nullable(TBase* t)
-{
- if (t) {
- return is_a<T, TBase>(t);
- } else {
- return false;
- }
-}
-
-template <class T, class TBase>
-T* dyn_cast(TBase* t)
-{
- assert(t != nullptr);
- if (T::IsInstance(t)) {
- return static_cast<T*>(t);
- } else {
- return nullptr;
- }
-}
-
-template <class T, class TBase>
-const T* dyn_cast(const TBase* t)
-{
- assert(t != nullptr);
- if (T::IsInstance(t)) {
- return static_cast<const T*>(t);
- } else {
- return nullptr;
- }
-}
-
-template <class T, class TBase>
-T* dyn_cast_nullable(TBase* t)
-{
- if (!t) return nullptr;
- return dyn_cast<T, TBase>(t);
-}
diff --git a/core/src/Utils/ScopeGuard.hpp b/core/src/Utils/ScopeGuard.hpp
deleted file mode 100644
index 28ffd0b..0000000
--- a/core/src/Utils/ScopeGuard.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include "Utils/Macros.hpp"
-
-#include <utility>
-
-template <class TCleanupFunc>
-class ScopeGuard
-{
-private:
- TCleanupFunc mFunc;
- bool mDismissed = false;
-
-public:
- /// Specifically left this implicit so that constructs like
- /// \code
- /// ScopeGuard sg = [&]() { res.Cleanup(); };
- /// \endcode
- /// would work. It is highly discourage and unlikely that one would want to use ScopeGuard as a function
- /// parameter, so the normal argument that implicit conversion are harmful doesn't really apply here.
- ScopeGuard(TCleanupFunc func)
- : mFunc{ std::move(func) }
- {
- }
-
- ~ScopeGuard()
- {
- if (!mDismissed) {
- mFunc();
- }
- }
-
- void Dismiss() noexcept
- {
- mDismissed = true;
- }
-};
-
-#define DEFER ScopeGuard UNIQUE_NAME(scopeGuard) = [&]()
diff --git a/core/src/Utils/Sigslot.cpp b/core/src/Utils/Sigslot.cpp
deleted file mode 100644
index 1132dfb..0000000
--- a/core/src/Utils/Sigslot.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-#include "Sigslot.hpp"
-
-#include <doctest/doctest.h>
-
-bool SignalStub::Connection::IsOccupied() const
-{
- return id != InvalidId;
-}
-
-SignalStub::SignalStub(IWrapper& wrapper)
- : mWrapper{ &wrapper }
-{
-}
-
-SignalStub::~SignalStub()
-{
- RemoveAllConnections();
-}
-
-std::span<const SignalStub::Connection> SignalStub::GetConnections() const
-{
- return mConnections;
-}
-
-SignalStub::Connection& SignalStub::InsertConnection(SlotGuard* guard)
-{
- Connection* result;
- int size = static_cast<int>(mConnections.size());
- for (int i = 0; i < size; ++i) {
- auto& conn = mConnections[i];
- if (!conn.IsOccupied()) {
- result = &conn;
- result->id = i;
- goto setup;
- }
- }
-
- mConnections.push_back(Connection{});
- result = &mConnections.back();
- result->id = size;
-
-setup:
- if (guard) {
- result->guard = guard;
- result->slotId = guard->InsertConnection(*this, result->id);
- }
- return *result;
-}
-
-void SignalStub::RemoveConnection(int id)
-{
- if (id >= 0 && id < mConnections.size()) {
- auto& conn = mConnections[id];
- if (conn.IsOccupied()) {
- mWrapper->RemoveFunction(conn.id);
- if (conn.guard) {
- conn.guard->RemoveConnection(conn.slotId);
- }
-
- conn.guard = nullptr;
- conn.slotId = SignalStub::InvalidId;
- conn.id = SignalStub::InvalidId;
- }
- }
-}
-
-void SignalStub::RemoveConnectionFor(SlotGuard& guard)
-{
- guard.RemoveConnectionFor(*this);
-}
-
-void SignalStub::RemoveAllConnections()
-{
- for (size_t i = 0; i < mConnections.size(); ++i) {
- RemoveConnection(i);
- }
-}
-
-SlotGuard::SlotGuard()
-{
-}
-
-SlotGuard::~SlotGuard()
-{
- DisconnectAll();
-}
-
-void SlotGuard::DisconnectAll()
-{
- for (auto& conn : mConnections) {
- if (conn.stub) {
- // Also calls SlotGuard::removeConnection, our copy of the data will be cleared in it
- conn.stub->RemoveConnection(conn.stubId);
- }
- }
-}
-
-int SlotGuard::InsertConnection(SignalStub& stub, int stubId)
-{
- int size = static_cast<int>(mConnections.size());
- for (int i = 0; i < size; ++i) {
- auto& conn = mConnections[i];
- if (!conn.stub) {
- conn.stub = &stub;
- conn.stubId = stubId;
- return i;
- }
- }
-
- mConnections.push_back(Connection{});
- auto& conn = mConnections.back();
- conn.stub = &stub;
- conn.stubId = stubId;
- return size;
-}
-
-void SlotGuard::RemoveConnectionFor(SignalStub& stub)
-{
- for (auto& conn : mConnections) {
- if (conn.stub == &stub) {
- conn.stub->RemoveConnection(conn.stubId);
- }
- }
-}
-
-void SlotGuard::RemoveConnection(int slotId)
-{
- mConnections[slotId] = {};
-}
-
-TEST_CASE("Signal connect and disconnect")
-{
- Signal<> sig;
-
- int counter = 0;
- int id = sig.Connect([&]() { counter++; });
-
- sig();
- CHECK(counter == 1);
-
- sig();
- CHECK(counter == 2);
-
- sig.Disconnect(id);
- sig();
- CHECK(counter == 2);
-}
-
-TEST_CASE("Signal with parameters")
-{
- Signal<int> sig;
-
- int counter = 0;
- int id = sig.Connect([&](int i) { counter += i; });
-
- sig(1);
- CHECK(counter == 1);
-
- sig(0);
- CHECK(counter == 1);
-
- sig(4);
- CHECK(counter == 5);
-
- sig.Disconnect(id);
- sig(1);
- CHECK(counter == 5);
-}
-
-TEST_CASE("Signal disconnectAll()")
-{
- Signal<> sig;
-
- int counter1 = 0;
- int counter2 = 0;
- sig.Connect([&]() { counter1++; });
- sig.Connect([&]() { counter2++; });
-
- sig();
- CHECK(counter1 == 1);
- CHECK(counter2 == 1);
-
- sig();
- CHECK(counter1 == 2);
- CHECK(counter2 == 2);
-
- sig.DisconnectAll();
- sig();
- CHECK(counter1 == 2);
- CHECK(counter2 == 2);
-}
-
-TEST_CASE("SlotGuard auto-disconnection")
-{
- int counter1 = 0;
- int counter2 = 0;
- Signal<> sig;
-
- {
- SlotGuard guard;
- sig.Connect(guard, [&]() { counter1 += 1; });
- sig.Connect(guard, [&]() { counter2 += 1; });
-
- sig();
- CHECK(counter1 == 1);
- CHECK(counter2 == 1);
-
- sig();
- CHECK(counter1 == 2);
- CHECK(counter2 == 2);
- }
-
- sig();
- CHECK(counter1 == 2);
- CHECK(counter2 == 2);
-}
-
-TEST_CASE("Signal destruct before SlotGuard")
-{
- int counter = 0;
- SlotGuard guard;
-
- {
- Signal<> sig2;
- sig2.Connect(guard, [&]() { counter++; });
-
- sig2();
- CHECK(counter == 1);
- }
-
- // Shouldn't error
- guard.DisconnectAll();
-}
diff --git a/core/src/Utils/Sigslot.hpp b/core/src/Utils/Sigslot.hpp
deleted file mode 100644
index 5638f12..0000000
--- a/core/src/Utils/Sigslot.hpp
+++ /dev/null
@@ -1,165 +0,0 @@
-#pragma once
-
-#include "Utils/fwd.hpp"
-
-#include <cstddef>
-#include <functional>
-#include <span>
-#include <utility>
-#include <vector>
-
-class SignalStub
-{
-public:
- /// Non-template interface for Signal<T...> to implement (a barrier to stop template
- /// arguments propagation).
- class IWrapper
- {
- public:
- virtual ~IWrapper() = default;
- virtual void RemoveFunction(int id) = 0;
- };
-
- enum
- {
- InvalidId = -1,
- };
-
- struct Connection
- {
- SlotGuard* guard;
- int slotId;
- int id = InvalidId; // If `InvalidId`, then this "spot" is unused
-
- bool IsOccupied() const;
- };
-
-private:
- std::vector<Connection> mConnections;
- IWrapper* mWrapper;
-
-private:
- template <class...>
- friend class Signal;
- friend class SlotGuard;
-
- SignalStub(IWrapper& wrapper);
- ~SignalStub();
-
- SignalStub(const SignalStub&) = delete;
- SignalStub& operator=(const SignalStub&) = delete;
- SignalStub(SignalStub&&) = default;
- SignalStub& operator=(SignalStub&&) = default;
-
- std::span<const Connection> GetConnections() const;
- Connection& InsertConnection(SlotGuard* guard = nullptr);
- void RemoveConnection(int id);
- void RemoveConnectionFor(SlotGuard& guard);
- void RemoveAllConnections();
-};
-
-template <class... TArgs>
-class Signal : public SignalStub::IWrapper
-{
-private:
- // Must be in this order so that mFunctions is still intact when mStub's destructor runs
- std::vector<std::function<void(TArgs...)>> mFunctions;
- SignalStub mStub;
-
-public:
- Signal()
- : mStub(*this)
- {
- }
-
- virtual ~Signal() = default;
-
- Signal(const Signal&) = delete;
- Signal& operator=(const Signal&) = delete;
- Signal(Signal&&) = default;
- Signal& operator=(Signal&&) = default;
-
- void operator()(TArgs... args)
- {
- for (auto& conn : mStub.GetConnections()) {
- if (conn.IsOccupied()) {
- mFunctions[conn.id](std::forward<TArgs>(args)...);
- }
- }
- }
-
- template <class TFunction>
- int Connect(TFunction slot)
- {
- auto& conn = mStub.InsertConnection();
- mFunctions.resize(std::max(mFunctions.size(), (size_t)conn.id + 1));
- mFunctions[conn.id] = std::move(slot);
- return conn.id;
- }
-
- template <class TFunction>
- int Connect(SlotGuard& guard, TFunction slot)
- {
- auto& conn = mStub.InsertConnection(&guard);
- mFunctions.resize(std::max(mFunctions.size(), (size_t)conn.id + 1));
- mFunctions[conn.id] = std::move(slot);
- return conn.id;
- }
-
- void Disconnect(int id)
- {
- mStub.RemoveConnection(id);
- }
-
- void DisconnectFor(SlotGuard& guard)
- {
- mStub.RemoveConnectionFor(guard);
- }
-
- void DisconnectAll()
- {
- mStub.RemoveAllConnections();
- }
-
- virtual void RemoveFunction(int id)
- {
- mFunctions[id] = {};
- }
-};
-
-/// Automatic disconnection mechanism for Signal<>.
-/// Bind connection to this guard by using the Connect(SlotGuard&, TFunction) overload.
-/// Either DisconnectAll() or the destructor disconnects all connections bound to this guard.
-class SlotGuard
-{
-private:
- struct Connection
- {
- SignalStub* stub = nullptr;
- int stubId = SignalStub::InvalidId;
- };
- std::vector<Connection> mConnections;
-
-public:
- friend class SignalStub;
- SlotGuard();
- ~SlotGuard();
-
- SlotGuard(const SlotGuard&) = delete;
- SlotGuard& operator=(const SlotGuard&) = delete;
- SlotGuard(SlotGuard&&) = default;
- SlotGuard& operator=(SlotGuard&&) = default;
-
- /// DisconnectBySource all connection associated with this SlotGuard.
- void DisconnectAll();
-
-private:
- /// \return Slot id.
- int InsertConnection(SignalStub& stub, int stubId);
- /// Remove the connection data in this associated with slotId. This does not invoke
- /// the connections' stub's RemoveConnection function.
- void RemoveConnection(int slotId);
- /// DisconnectBySource all connections from the given stub associated with this SlotGuard.
- /// Implementation for SignalStub::RemoveConnectionsFor(SlotGuard&)
- void RemoveConnectionFor(SignalStub& stub);
-};
diff --git a/core/src/Utils/Size.hpp b/core/src/Utils/Size.hpp
deleted file mode 100644
index 98be41a..0000000
--- a/core/src/Utils/Size.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-#include "Utils/Vector.hpp"
-
-template <class T>
-class Size2 {
-public:
- T width;
- T height;
-
-public:
- Size2()
- : width{ 0 }, height{ 0 } {
- }
-
- Size2(T width, T height)
- : width{ width }, height{ height } {
- }
-
- Size2(Vec2<T> vec)
- : width{ vec.x }, height{ vec.y }
- {
- }
-
- operator Vec2<T>() const
- {
- return { width, height };
- }
-
- Vec2<T> AsVec() const
- {
- return { width, height };
- }
-
- friend bool operator==(const Size2<T>&, const Size2<T>&) = default;
-
- template <class TTarget>
- Size2<TTarget> Cast() const
- {
- return {
- static_cast<TTarget>(width),
- static_cast<TTarget>(height),
- };
- }
-};
-
-template <class T>
-Size2<T> operator+(Size2<T> a, Size2<T> b) {
- return { a.width + b.width, a.height + b.height };
-}
-
-template <class T>
-Size2<T> operator-(Size2<T> a, Size2<T> b) {
- return { a.width - b.width, a.height - b.height };
-}
-
-template <class T, class N>
-auto operator*(Size2<T> a, N mult) -> Size2<decltype(a.width * mult)> {
- return { a.width * mult, a.height * mult };
-}
-
-template <class T, class N>
-auto operator/(Size2<T> a, N mult) -> Size2<decltype(a.width / mult)> {
- return { a.width / mult, a.height / mult };
-}
diff --git a/core/src/Utils/StandardDirectories.cpp b/core/src/Utils/StandardDirectories.cpp
deleted file mode 100644
index 2202f51..0000000
--- a/core/src/Utils/StandardDirectories.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "StandardDirectories.hpp"
-
-#include <filesystem>
-#include <stdexcept>
-
-namespace fs = std::filesystem;
-
-#if defined(_WIN32)
-// https://stackoverflow.com/questions/54499256/how-to-find-the-saved-games-folder-programmatically-in-c-c
-# include <ShlObj_core.h>
-# include <objbase.h>
-# pragma comment(lib, "shell32.lib")
-# pragma comment(lib, "ole32.lib")
-
-static fs::path GetAppDataRoaming()
-{
- PWSTR path = nullptr;
- HRESULT hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE, nullptr, &path);
- if (SUCCEEDED(hr)) {
- auto dataDir = fs::path(path);
- CoTaskMemFree(path);
-
- fs::create_directories(dataDir);
- return dataDir;
- } else {
- fs::path dataDir("~/AppData/Roaming");
- fs::create_directories(dataDir);
- return dataDir;
- }
-}
-
-#elif defined(__APPLE__)
-// TODO
-#elif defined(__linux__)
-# include <cstdlib>
-
-static fs::path GetEnvVar(const char* name, const char* backup)
-{
- if (const char* path = std::getenv(name)) {
- fs::path dataDir(path);
- fs::create_directories(dataDir);
- return dataDir;
- } else {
- fs::path dataDir(backup);
- fs::create_directories(dataDir);
- return dataDir;
- }
-}
-
-#endif
-
-const std::filesystem::path& StandardDirectories::UserData()
-{
- static auto userDataDir = []() -> fs::path {
-#if defined(_WIN32)
- return GetAppDataRoaming();
-#elif defined(__APPLE__)
- // TODO where?
-#elif defined(__linux__)
- return GetEnvVar("XDG_DATA_HOME", "~/.local/share");
-#endif
- }();
- return userDataDir;
-}
-
-const std::filesystem::path& StandardDirectories::UserConfig()
-{
- static auto userConfigDir = []() -> fs::path {
-#if defined(_WIN32)
- return GetAppDataRoaming();
-#elif defined(__APPLE__)
- // TODO where?
-#elif defined(__linux__)
- return GetEnvVar("XDG_CONFIG_HOME", "~/.config");
-#endif
- }();
- return userConfigDir;
-}
diff --git a/core/src/Utils/StandardDirectories.hpp b/core/src/Utils/StandardDirectories.hpp
deleted file mode 100644
index 4f7e5e2..0000000
--- a/core/src/Utils/StandardDirectories.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-#include <filesystem>
-
-namespace StandardDirectories {
-
-const std::filesystem::path& UserData();
-const std::filesystem::path& UserConfig();
-
-} // namespace StandardDirectories
diff --git a/core/src/Utils/Time.cpp b/core/src/Utils/Time.cpp
deleted file mode 100644
index 4e79ffa..0000000
--- a/core/src/Utils/Time.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "Time.hpp"
-
-#include <ctime>
-
-std::string TimeUtils::StringifyTimePoint(std::chrono::time_point<std::chrono::system_clock> tp)
-{
- auto t = std::chrono::system_clock::to_time_t(tp);
-
- char data[32];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations" // C++ doesn't have std::localtime_s
- std::strftime(data, sizeof(data), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
-#pragma clang diagnostic pop
-
- return std::string(data);
-}
-
-std::string TimeUtils::StringifyTimeStamp(int64_t timeStamp)
-{
- if (timeStamp == 0) {
- return "";
- }
-
- namespace chrono = std::chrono;
- chrono::milliseconds d{ timeStamp };
- chrono::time_point<chrono::system_clock> tp{ d };
-
- return StringifyTimePoint(tp);
-}
diff --git a/core/src/Utils/Time.hpp b/core/src/Utils/Time.hpp
deleted file mode 100644
index fbbd3b2..0000000
--- a/core/src/Utils/Time.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include <chrono>
-#include <string>
-
-namespace TimeUtils {
-
-std::string StringifyTimePoint(std::chrono::time_point<std::chrono::system_clock> tp);
-std::string StringifyTimeStamp(int64_t timeStamp);
-
-} // namespace TimeUtils
diff --git a/core/src/Utils/UUID.hpp b/core/src/Utils/UUID.hpp
deleted file mode 100644
index 9044aa6..0000000
--- a/core/src/Utils/UUID.hpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <uuid.h>
diff --git a/core/src/Utils/Variant.hpp b/core/src/Utils/Variant.hpp
deleted file mode 100644
index df2f882..0000000
--- a/core/src/Utils/Variant.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include <utility>
-#include <variant>
-
-template <class... Ts>
-struct Overloaded : Ts...
-{
- using Ts::operator()...;
-};
-template <class... Ts>
-Overloaded(Ts...) -> Overloaded<Ts...>;
-
-template <class... Args>
-struct VariantCastProxy
-{
- std::variant<Args...> v;
-
- template <class... ToArgs>
- operator std::variant<ToArgs...>() const
- {
- return std::visit(
- [](auto&& arg) -> std::variant<ToArgs...> { return arg; },
- v);
- }
-};
-
-/// Use snake_case naming to align with `static_cast`, `dynamic_cast`, etc..
-template <class... Args>
-auto variant_cast(std::variant<Args...> v) -> VariantCastProxy<Args...>
-{
- return { std::move(v) };
-}
diff --git a/core/src/Utils/Vector.hpp b/core/src/Utils/Vector.hpp
deleted file mode 100644
index 4d3f3b3..0000000
--- a/core/src/Utils/Vector.hpp
+++ /dev/null
@@ -1,144 +0,0 @@
-#pragma once
-
-#include "Utils/IO/DataStream.hpp"
-
-template <class T>
-struct Vec2
-{
- T x = 0;
- T y = 0;
-
- template <class TTarget>
- Vec2<TTarget> Cast() const
- {
- return {
- static_cast<TTarget>(x),
- static_cast<TTarget>(y),
- };
- }
-
- void ReadFromDataStream(InputDataStream& stream)
- {
- stream.Value(x);
- stream.Value(y);
- }
-
- void WriteToDataStream(OutputDataStream& stream) const
- {
- stream.Value(x);
- stream.Value(y);
- }
-
- friend constexpr bool operator==(const Vec2& a, const Vec2& b) = default;
-
- friend constexpr Vec2 operator+(const Vec2& a, const Vec2& b) { return { a.x + b.x, a.y + b.y }; }
- friend constexpr Vec2 operator-(const Vec2& a, const Vec2& b) { return { a.x - b.x, a.y - b.y }; }
- friend constexpr Vec2 operator*(const Vec2& a, const Vec2& b) { return { a.x * b.x, a.y * b.y }; }
- friend constexpr Vec2 operator/(const Vec2& a, const Vec2& b) { return { a.x / b.x, a.y / b.y }; }
-
- friend constexpr Vec2 operator+(const Vec2& a, T n) { return { a.x + n, a.y + n }; }
- friend constexpr Vec2 operator-(const Vec2& a, T n) { return { a.x - n, a.y - n }; }
- friend constexpr Vec2 operator*(const Vec2& a, T n) { return { a.x * n, a.y * n }; }
- friend constexpr Vec2 operator/(const Vec2& a, T n) { return { a.x / n, a.y / n }; }
-};
-
-using Vec2i = Vec2<int>;
-using Vec2f = Vec2<float>;
-
-template <class T>
-struct Vec3
-{
- T x = 0;
- T y = 0;
- T z = 0;
-
- template <class TTarget>
- Vec3<TTarget> Cast() const
- {
- return {
- static_cast<TTarget>(x),
- static_cast<TTarget>(y),
- static_cast<TTarget>(z),
- };
- }
-
- void ReadFromDataStream(InputDataStream& stream)
- {
- stream.Value(x);
- stream.Value(y);
- stream.Value(z);
- }
-
- void WriteToDataStream(OutputDataStream& stream) const
- {
- stream.Value(x);
- stream.Value(y);
- stream.Value(z);
- }
-
- friend constexpr bool operator==(const Vec3& a, const Vec3& b) = default;
-
- friend constexpr Vec3 operator+(const Vec3& a, const Vec3& b) { return { a.x + b.x, a.y + b.y, a.z + b.z }; }
- friend constexpr Vec3 operator-(const Vec3& a, const Vec3& b) { return { a.x - b.x, a.y - b.y, a.z - b.z }; }
- friend constexpr Vec3 operator*(const Vec3& a, const Vec3& b) { return { a.x * b.x, a.y * b.y, a.z * b.z }; }
- friend constexpr Vec3 operator/(const Vec3& a, const Vec3& b) { return { a.x / b.x, a.y / b.y, a.z / b.z }; }
-
- friend constexpr Vec3 operator+(const Vec3& a, T n) { return { a.x + n, a.y + n, a.z + n }; }
- friend constexpr Vec3 operator-(const Vec3& a, T n) { return { a.x - n, a.y - n, a.z - n }; }
- friend constexpr Vec3 operator*(const Vec3& a, T n) { return { a.x * n, a.y * n, a.z * n }; }
- friend constexpr Vec3 operator/(const Vec3& a, T n) { return { a.x / n, a.y / n, a.z / n }; }
-};
-
-using Vec3i = Vec3<int>;
-using Vec3f = Vec3<float>;
-
-template <class T>
-struct Vec4
-{
- T x = 0;
- T y = 0;
- T z = 0;
- T w = 0;
-
- template <class TTarget>
- Vec4<TTarget> Cast() const
- {
- return {
- static_cast<TTarget>(x),
- static_cast<TTarget>(y),
- static_cast<TTarget>(z),
- static_cast<TTarget>(w),
- };
- }
-
- void ReadFromDataStream(InputDataStream& stream)
- {
- stream.Value(x);
- stream.Value(y);
- stream.Value(z);
- stream.Value(w);
- }
-
- void WriteToDataStream(OutputDataStream& stream) const
- {
- stream.Value(x);
- stream.Value(y);
- stream.Value(z);
- stream.Value(w);
- }
-
- friend constexpr bool operator==(const Vec4& a, const Vec4& b) = default;
-
- friend constexpr Vec4 operator+(const Vec4& a, const Vec4& b) { return { a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
- friend constexpr Vec4 operator-(const Vec4& a, const Vec4& b) { return { a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
- friend constexpr Vec4 operator*(const Vec4& a, const Vec4& b) { return { a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
- friend constexpr Vec4 operator/(const Vec4& a, const Vec4& b) { return { a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
-
- friend constexpr Vec4 operator+(const Vec4& a, T n) { return { a.x + n, a.y + n, a.z + n, a.w + n }; }
- friend constexpr Vec4 operator-(const Vec4& a, T n) { return { a.x - n, a.y - n, a.z - n, a.w - n }; }
- friend constexpr Vec4 operator*(const Vec4& a, T n) { return { a.x * n, a.y * n, a.z * n, a.w * n }; }
- friend constexpr Vec4 operator/(const Vec4& a, T n) { return { a.x / n, a.y / n, a.z / n, a.w / n }; }
-};
-
-using Vec4i = Vec4<int>;
-using Vec4f = Vec4<float>;
diff --git a/core/src/Utils/VectorHash.hpp b/core/src/Utils/VectorHash.hpp
deleted file mode 100644
index 7df9c35..0000000
--- a/core/src/Utils/VectorHash.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-
-#include "Utils/Hash.hpp"
-#include "Utils/Vector.hpp"
-
-#include <cstddef>
-#include <functional>
-
-template <class T>
-struct std::hash<Vec2<T>>
-{
- size_t operator()(const Vec2<T>& vec) const
- {
- size_t result;
- HashUtils::Combine(result, vec.x);
- HashUtils::Combine(result, vec.y);
- return result;
- }
-};
-
-template <class T>
-struct std::hash<Vec3<T>>
-{
- size_t operator()(const Vec3<T>& vec) const
- {
- size_t result;
- HashUtils::Combine(result, vec.x);
- HashUtils::Combine(result, vec.y);
- HashUtils::Combine(result, vec.z);
- return result;
- }
-};
-
-template <class T>
-struct std::hash<Vec4<T>>
-{
- size_t operator()(const Vec4<T>& vec) const
- {
- size_t result;
- HashUtils::Combine(result, vec.x);
- HashUtils::Combine(result, vec.y);
- HashUtils::Combine(result, vec.z);
- HashUtils::Combine(result, vec.w);
- return result;
- }
-};
diff --git a/core/src/Utils/fwd.hpp b/core/src/Utils/fwd.hpp
deleted file mode 100644
index c740bd1..0000000
--- a/core/src/Utils/fwd.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include "Utils/IO/fwd.hpp"
-
-// Color.hpp
-class RgbaColor;
-class HsvColor;
-
-// Sigslot.hpp
-class SignalStub;
-template <class... TArgs>
-class Signal;
-class SlotGuard;
-
-// String.hpp
-class Utf8Iterator;
-class Utf8IterableString;