summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2021-09-04 17:58:56 -0700
committerrtk0c <[email protected]>2021-09-04 17:58:56 -0700
commit70e00f817e9596a746800ba4afec2b7c4ca25142 (patch)
tree52ca5f993034c6dcb7353805450e66cefc5a0481 /core/src
parent500aa5130f3f5ad211749018d7be9b0ab46c12b4 (diff)
Migrate Template and TableTemplate to use DataStream
Diffstat (limited to 'core/src')
-rw-r--r--core/src/Model/Assets.cpp4
-rw-r--r--core/src/Model/Template/TableTemplate.cpp56
-rw-r--r--core/src/Model/Template/TableTemplate.hpp14
-rw-r--r--core/src/Model/Template/Template.hpp9
-rw-r--r--core/src/UI/UI_Templates.cpp2
-rw-r--r--core/src/Utils/IO/DataStream.hpp73
-rw-r--r--core/src/Utils/IO/StringIntegration.hpp6
-rw-r--r--core/src/Utils/IO/TslArrayIntegration.hpp58
-rw-r--r--core/src/Utils/IO/TslRobinIntegration.hpp102
-rw-r--r--core/src/Utils/IO/UuidIntegration.hpp4
-rw-r--r--core/src/Utils/IO/VectorIntegration.hpp38
-rw-r--r--core/src/Utils/Vector.hpp24
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 }; }