diff options
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/Model/Assets.cpp | 4 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.cpp | 56 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.hpp | 14 | ||||
-rw-r--r-- | core/src/Model/Template/Template.hpp | 9 | ||||
-rw-r--r-- | core/src/UI/UI_Templates.cpp | 2 | ||||
-rw-r--r-- | core/src/Utils/IO/DataStream.hpp | 73 | ||||
-rw-r--r-- | core/src/Utils/IO/StringIntegration.hpp | 6 | ||||
-rw-r--r-- | core/src/Utils/IO/TslArrayIntegration.hpp | 58 | ||||
-rw-r--r-- | core/src/Utils/IO/TslRobinIntegration.hpp | 102 | ||||
-rw-r--r-- | core/src/Utils/IO/UuidIntegration.hpp | 4 | ||||
-rw-r--r-- | core/src/Utils/IO/VectorIntegration.hpp | 38 | ||||
-rw-r--r-- | core/src/Utils/Vector.hpp | 24 |
12 files changed, 345 insertions, 45 deletions
diff --git a/core/src/Model/Assets.cpp b/core/src/Model/Assets.cpp index 045a46f..80c2fa4 100644 --- a/core/src/Model/Assets.cpp +++ b/core/src/Model/Assets.cpp @@ -19,8 +19,8 @@ namespace fs = std::filesystem; template <class TProxy> void SavedAsset::OperateIOProxy(TProxy& proxy) { - proxy.ObjectAdapted(Name, DataStreamAdapters::String{}); - proxy.ObjectAdapted(Uuid, DataStreamAdapters::Uuid{}); + proxy.template ObjectAdapted<DataStreamAdapters::String>(Name); + proxy.template ObjectAdapted<DataStreamAdapters::Uuid>(Uuid); proxy.Value(Payload); } diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp index adf79fe..a5745c7 100644 --- a/core/src/Model/Template/TableTemplate.cpp +++ b/core/src/Model/Template/TableTemplate.cpp @@ -1,7 +1,14 @@ #include "TableTemplate.hpp" +#include "Utils/IO/StringIntegration.hpp" +#include "Utils/IO/TslArrayIntegration.hpp" +#include "Utils/IO/VectorIntegration.hpp" + #include <xlsxwriter.h> +#include <algorithm> #include <charconv> +#include <cstddef> +#include <cstdint> #include <iostream> #include <map> @@ -20,6 +27,23 @@ bool TableCell::IsMergedCell() const return PrimaryCellLocation.x == -1 || PrimaryCellLocation.y == -1; } +template <class TProxy> +void TableCell::OperateIOProxy(TProxy& proxy) +{ + proxy.template ObjectAdapted<DataStreamAdapters::String>(Content); + proxy.Object(Location); + proxy.Object(PrimaryCellLocation); + proxy.Value(SpanX); + proxy.Value(SpanY); + proxy.Value(HorizontalAlignment); + proxy.Value(VerticalAlignment); + proxy.Value(Type); + proxy.Value(DataId); +} + +template void TableCell::OperateIOProxy(InputDataStream& adapter); +template void TableCell::OperateIOProxy(OutputDataStream& adapter); + Vec2i TableArrayGroup::GetLeftCell() const { return { Row, LeftCell }; @@ -62,6 +86,17 @@ bool TableArrayGroup::UpdateCellName(std::string_view oldName, std::string_view return ::UpdateElementName(mName2Cell, oldName, newName); } +template <class TProxy> +void TableArrayGroup::OperateIOProxy(TProxy& proxy) +{ + proxy.Value(Row); + proxy.Value(LeftCell); + proxy.Value(RightCell); +} + +template void TableArrayGroup::OperateIOProxy(InputDataStream& adapter); +template void TableArrayGroup::OperateIOProxy(OutputDataStream& adapter); + TableInstantiationParameters::TableInstantiationParameters(const TableTemplate& table) : mTable{ &table } { @@ -513,13 +548,24 @@ lxw_worksheet* TableTemplate::InstantiateToExcelWorksheet(lxw_workbook* workbook return worksheet; } -Template::ReadResult TableTemplate::ReadFrom(std::istream& stream) + +void TableTemplate::ReadFromDataStream(InputDataStream& stream) +{ + OperateIOProxy(stream); +} + +void TableTemplate::WriteToDataStream(OutputDataStream& stream) { - // TODO - return ReadResult::RR_Success; + OperateIOProxy(stream); } -void TableTemplate::WriteTo(std::ostream& stream) const +template <class TProxy> +void TableTemplate::OperateIOProxy(TProxy& proxy) { - // TODO + proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(mColumnWidths); + proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(mRowHeights); + proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(mCells); + proxy.template ObjectAdapted<DataStreamAdapters::Vector<>>(mArrayGroups); + proxy.template ObjectAdapted<DataStreamAdapters::TslArrayMap<>>(mName2Parameters); + proxy.template ObjectAdapted<DataStreamAdapters::TslArrayMap<>>(mName2ArrayGroups); } diff --git a/core/src/Model/Template/TableTemplate.hpp b/core/src/Model/Template/TableTemplate.hpp index c651ce1..c6617b0 100644 --- a/core/src/Model/Template/TableTemplate.hpp +++ b/core/src/Model/Template/TableTemplate.hpp @@ -53,6 +53,9 @@ public: bool IsPrimaryCell() const; /// Return whether this cell is a part of a merged range or not. Includes the primary cell. bool IsMergedCell() const; + + template <class TProxy> + void OperateIOProxy(TProxy& proxy); }; // TODO support reverse (bottom to top) filling order @@ -105,6 +108,9 @@ public: /// Find the location of the cell within this array group that has the given name. Vec2i FindCell(std::string_view name); bool UpdateCellName(std::string_view oldName, std::string_view newName); + + template <class TProxy> + void OperateIOProxy(TProxy& proxy); }; // Forward declaration of libxlsxwriter structs @@ -211,6 +217,10 @@ public: lxw_workbook* InstantiateToExcelWorkbook(const TableInstantiationParameters& params) const; lxw_worksheet* InstantiateToExcelWorksheet(lxw_workbook* workbook, const TableInstantiationParameters& params) const; - ReadResult ReadFrom(std::istream& stream) override; - void WriteTo(std::ostream& stream) const override; + void ReadFromDataStream(InputDataStream& stream) override; + void WriteToDataStream(OutputDataStream& stream) override; + +private: + template <class TProxy> + void OperateIOProxy(TProxy& proxy); }; diff --git a/core/src/Model/Template/Template.hpp b/core/src/Model/Template/Template.hpp index 30fdc75..c6b93e2 100644 --- a/core/src/Model/Template/Template.hpp +++ b/core/src/Model/Template/Template.hpp @@ -35,13 +35,8 @@ public: Kind GetKind() const; - enum ReadResult - { - RR_Success, - RR_InvalidFormat, - }; - virtual ReadResult ReadFrom(std::istream& stream) = 0; - virtual void WriteTo(std::ostream& stream) const = 0; + virtual void ReadFromDataStream(InputDataStream& stream) = 0; + virtual void WriteToDataStream(OutputDataStream& stream) = 0; }; class TemplateAssetList final : public AssetListTyped<Template> diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp index ebf5f62..88ab5fc 100644 --- a/core/src/UI/UI_Templates.cpp +++ b/core/src/UI/UI_Templates.cpp @@ -462,7 +462,7 @@ private: } } if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(I18N_TEXT("Name of the parameter lnk to this cell; local within the array group.", L10N_TABLE_CELL_ARRAY_VAR_TOOLTIP)); + ImGui::SetTooltip(I18N_TEXT("Name of the parameter link to this cell; local within the array group.", L10N_TABLE_CELL_ARRAY_VAR_TOOLTIP)); } if (mAS.ErrorDuplicateVarName) { diff --git a/core/src/Utils/IO/DataStream.hpp b/core/src/Utils/IO/DataStream.hpp index fa22549..58fae7d 100644 --- a/core/src/Utils/IO/DataStream.hpp +++ b/core/src/Utils/IO/DataStream.hpp @@ -60,6 +60,15 @@ public: 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) { @@ -72,10 +81,26 @@ public: } } - template <class TObject, class TAdapter> - void ReadObjectAdapted(TObject& obj, TAdapter&& adapter) + /// Helper to invoke either Read() or ReadObject(). Note that this function doesn't account for types that needs and adapter. + /// 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 T> + void ReadGeneric(T& t) + { + if constexpr (requires(T tt, InputDataStream ss) { ss.Read(tt); }) { + Read(t); + } else if constexpr (requires(T tt, InputDataStream ss) { ss.ReadEnum(tt); }) { + ReadEnum(t); + } else if constexpr (requires(T tt, InputDataStream ss) { ss.ReadObject(tt); }) { + ReadObject(t); + } else { + static_assert(false && sizeof(T), "This type is neither a 'value' nor an 'object'."); + } + } + + template <class TAdapter, class TObject> + void ReadObjectAdapted(TObject& obj) { - adapter.ReadFromDataStream(*this, obj); + TAdapter::ReadFromDataStream(*this, obj); } public: @@ -99,10 +124,10 @@ public: ReadObject(obj); } - template <class TObject, class TAdapter> - void ObjectAdapted(TObject& obj, TAdapter&& adapter) + template <class TAdapter, class TObject> + void ObjectAdapted(TObject& obj) { - ReadObjectAdapted(obj, adapter); + ReadObjectAdapted<TAdapter>(obj); } }; @@ -146,6 +171,14 @@ public: 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(TObject& obj) { @@ -158,10 +191,26 @@ public: } } - template <class TObject, class TAdapter> - void WriteObjectAdapted(TObject& obj, TAdapter&& adapter) + /// Helper to invoke either Write() or WriteObject(). Note that this function doesn't account for types that needs and adapter. + /// 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 T> + void WriteGeneric(T& t) + { + if constexpr (requires(T tt, OutputDataStream ss) { ss.Write(tt); }) { + Write(t); + } else if constexpr (requires(T tt, OutputDataStream ss) { ss.WriteEnum(tt); }) { + WriteEnum(t); + } else if constexpr (requires(T tt, OutputDataStream ss) { ss.WriteObject(tt); }) { + WriteObject(t); + } else { + static_assert(false && sizeof(T), "This type is neither a 'value' nor an 'object'."); + } + } + + template <class TAdapter, class TObject> + void WriteObjectAdapted(TObject& obj) { - adapter.WriteToDataStream(*this, obj); + TAdapter::WriteToDataStream(*this, obj); } public: @@ -185,9 +234,9 @@ public: WriteObject(obj); } - template <class TObject, class TAdapter> - void ObjectAdapted(TObject& obj, TAdapter&& adapter) + template <class TAdapter, class TObject> + void ObjectAdapted(TObject& obj) { - WriteObjectAdapted(obj, adapter); + WriteObjectAdapted<TAdapter>(obj); } }; diff --git a/core/src/Utils/IO/StringIntegration.hpp b/core/src/Utils/IO/StringIntegration.hpp index 8c5588c..20dc882 100644 --- a/core/src/Utils/IO/StringIntegration.hpp +++ b/core/src/Utils/IO/StringIntegration.hpp @@ -9,7 +9,7 @@ namespace DataStreamAdapters { struct String { - void ReadFromDataStream(InputDataStream& s, std::string& str) + static void ReadFromDataStream(InputDataStream& s, std::string& str) { uint64_t size; s.Read(size); @@ -19,7 +19,7 @@ struct String s.ReadBytes(size, std::back_inserter(str)); } - void WriteToDataStream(OutputDataStream& s, const std::string& str) + static void WriteToDataStream(OutputDataStream& s, const std::string& str) { s.Write((uint64_t)str.size()); s.WriteBytes(str.size(), str.data()); @@ -28,7 +28,7 @@ struct String struct StringView { - void WriteToDataStream(OutputDataStream& s, const std::string_view& str) + static void WriteToDataStream(OutputDataStream& s, const std::string_view& str) { s.Write((uint64_t)str.size()); s.WriteBytes(str.size(), str.data()); diff --git a/core/src/Utils/IO/TslArrayIntegration.hpp b/core/src/Utils/IO/TslArrayIntegration.hpp new file mode 100644 index 0000000..eebea02 --- /dev/null +++ b/core/src/Utils/IO/TslArrayIntegration.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include "Utils/IO/DataStream.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& s, tsl::robin_map<char, TValue>& map) + { + static_assert(std::is_default_constructible_v<TValue>); + static_assert(std::is_move_constructible_v<TValue>); + + uint64_t size; + s.Read(size); + map.reserve(size); + + for (uint64_t i = 0; i < size; ++i) { + std::string key; + s.ReadObjectAdapted<DataStreamAdapters::String>(key); + + TValue value; + if constexpr (std::is_same_v<TAdapter, void>) { + s.ReadGeneric(value); + } else { + s.ReadObjectAdapted<TAdapter>(value); + } + + map.insert(key, std::move(value)); + } + } + + template <class TValue> + static void WriteToDataStream(OutputDataStream& s, const tsl::robin_map<char, TValue>& map) + { + s.Write((uint64_t)map.size()); + + for (auto it = map.begin(); it != map.end(); ++it) { + s.WriteObjectAdapted<DataStreamAdapters::StringView>(it.key_sv()); + + if constexpr (std::is_same_v<TAdapter, void>) { + s.WriteGeneric(it.value()); + } else { + s.WriteObjectAdapted<TAdapter>(it.value()); + } + } + } +}; +} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/TslRobinIntegration.hpp b/core/src/Utils/IO/TslRobinIntegration.hpp new file mode 100644 index 0000000..c800e52 --- /dev/null +++ b/core/src/Utils/IO/TslRobinIntegration.hpp @@ -0,0 +1,102 @@ +#pragma once + +#include "Utils/IO/DataStream.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& s, 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; + s.Read(size); + map.reserve(size); + + for (uint64_t i = 0; i < size; ++i) { + TKey key; + if constexpr (std::is_same_v<TKeyAdapter, void>) { + s.ReadGeneric(key); + } else { + s.ReadObjectAdapted<TKeyAdapter>(key); + } + + TValue value; + if constexpr (std::is_same_v<TValueAdapter, void>) { + s.ReadGeneric(value); + } else { + s.ReadObjectAdapted<TValueAdapter>(value); + } + + map.insert(std::move(key), std::move(value)); + } + } + + template <class TKey, class TValue> + static void WriteToDataStream(OutputDataStream& s, const tsl::robin_map<TKey, TValue>& map) + { + s.Write((uint64_t)map.size()); + + for (auto it = map.begin(); it != map.end(); ++it) { + if constexpr (std::is_same_v<TKeyAdapter, void>) { + s.WriteGeneric(it.key()); + } else { + s.WriteObjectAdapted<TKeyAdapter>(it.key()); + } + + if constexpr (std::is_same_v<TValueAdapter, void>) { + s.WriteGeneric(it.value()); + } else { + s.WriteObjectAdapted<TValueAdapter>(it.value()); + } + } + } +}; + +template <class TAdapter = void> +struct TslRobinSet +{ + template <class TElement> + static void ReadFromDataStream(InputDataStream& s, tsl::robin_set<TElement>& set) + { + static_assert(std::is_default_constructible_v<TElement>); + static_assert(std::is_move_constructible_v<TElement>); + + uint64_t size; + s.Read(size); + set.reserve(size); + + for (uint64_t i = 0; i < size; ++i) { + TElement element; + if constexpr (std::is_same_v<TAdapter, void>) { + s.ReadGeneric(element); + } else { + s.ReadObjectAdapted<TAdapter>(element); + } + + set.insert(std::move(element)); + } + } + + template <class TElement> + static void WriteToDataStream(OutputDataStream& s, const tsl::array_set<TElement>& set) + { + s.Write((uint64_t)set.size()); + + for (auto& element : set) { + if constexpr (std::is_same_v<TAdapter, void>) { + s.WriteGeneric(element); + } else { + s.WriteObjectAdapted<TAdapter>(element); + } + } + } +}; +} // namespace DataStreamAdapters diff --git a/core/src/Utils/IO/UuidIntegration.hpp b/core/src/Utils/IO/UuidIntegration.hpp index 605f821..d8a0304 100644 --- a/core/src/Utils/IO/UuidIntegration.hpp +++ b/core/src/Utils/IO/UuidIntegration.hpp @@ -10,7 +10,7 @@ namespace DataStreamAdapters { struct Uuid { - void ReadFromDataStream(InputDataStream& s, uuids::uuid& uuid) + static void ReadFromDataStream(InputDataStream& s, uuids::uuid& uuid) { uint8_t buffer[16]; s.ReadBytes(16, buffer); @@ -18,7 +18,7 @@ struct Uuid uuid = uuids::uuid(gsl::span<uint8_t, 16>{ buffer }); } - void WriteToDataStream(OutputDataStream& s, const uuids::uuid& uuid) + static void WriteToDataStream(OutputDataStream& s, const uuids::uuid& uuid) { auto gslSpan = uuid.as_bytes(); s.WriteBytes(gslSpan.size(), gslSpan.data()); diff --git a/core/src/Utils/IO/VectorIntegration.hpp b/core/src/Utils/IO/VectorIntegration.hpp index dedbf29..da663a4 100644 --- a/core/src/Utils/IO/VectorIntegration.hpp +++ b/core/src/Utils/IO/VectorIntegration.hpp @@ -2,31 +2,47 @@ #include "Utils/IO/DataStream.hpp" +#include <type_traits> #include <vector> namespace DataStreamAdapters { +template <class TAdapter = void> struct Vector { template <class TElement> - void ReadFromDataStream(InputDataStream& s, std::vecetor<TElement>& vec) + static void ReadFromDataStream(InputDataStream& s, std::vector<TElement>& vec) { - s.Write((uint64_t)vec.size()); - for (auto& element : vec) { - // TODO - } - } + static_assert(std::is_default_constructible_v<TElement>); + static_assert(std::is_move_constructible_v<TElement>); - template <class TElement> - void WriteToDataStream(OutputDataStream& s, const std::vecetor<TElement>& vec) - { uint64_t size; - s >> size; + s.Read(size); vec.clear(); vec.reserve(size); for (uint64_t i = 0; i < size; ++i) { - // TODO + TElement element; + if constexpr (std::is_same_v<TAdapter, void>) { + s.ReadGeneric(element); + } else { + s.ReadObjectAdapted<TAdapter>(element); + } + + vec.push_back(std::move(element)); + } + } + + template <class TElement> + static void WriteToDataStream(OutputDataStream& s, const std::vector<TElement>& vec) + { + s.Write((uint64_t)vec.size()); + for (auto& element : vec) { + if constexpr (std::is_same_v<TAdapter, void>) { + s.WriteGeneric(element); + } else { + s.WriteObjectAdapted<TAdapter>(element); + } } } }; diff --git a/core/src/Utils/Vector.hpp b/core/src/Utils/Vector.hpp index 7e71b73..3d4d251 100644 --- a/core/src/Utils/Vector.hpp +++ b/core/src/Utils/Vector.hpp @@ -15,6 +15,13 @@ struct Vec2 }; } + template <class TProxy> + void OperateIOProxy(TProxy& proxy) + { + proxy.Value(x); + proxy.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 }; } @@ -48,6 +55,14 @@ struct Vec3 }; } + template <class TProxy> + void OperateIOProxy(TProxy& proxy) + { + proxy.Value(x); + proxy.Value(y); + proxy.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 }; } @@ -83,6 +98,15 @@ struct Vec4 }; } + template <class TProxy> + void OperateIOProxy(TProxy& proxy) + { + proxy.Value(x); + proxy.Value(y); + proxy.Value(z); + proxy.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 }; } |