diff options
author | rtk0c <[email protected]> | 2022-06-27 18:27:13 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-06-27 18:27:13 -0700 |
commit | 8f0dda5eab181b0f14f2652b4e984aaaae3f258c (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/src/Utils | |
parent | fad6a88a13ab1f888ab25ad0aae19c1d63aa0623 (diff) |
Start from a clean slate
Diffstat (limited to 'core/src/Utils')
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; |