Skip to content

Commit d273ee3

Browse files
committed
Container/MeshNode: Operators
1 parent 2d9854a commit d273ee3

3 files changed

Lines changed: 217 additions & 38 deletions

File tree

modules/Container/MeshNetwork.mpp

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,98 @@ export namespace CppUtils::Container
9595
};
9696

9797
template<class Key, class Value>
98-
using MeshNodePtr = NetworkPtr<MeshNode<Key, Value>>;
98+
class MeshNodePtr final
99+
{
100+
public:
101+
using NodePtr = NetworkPtr<MeshNode<Key, Value>>;
102+
using SharedPtr = NodePtr::SharedPtr;
103+
104+
class Branch final
105+
{
106+
public:
107+
Branch(SharedPtr& self, const Key& key): m_self(self), m_key(key) {}
108+
109+
auto operator>>(MeshNodePtr<Key, Value>& other) -> MeshNodePtr<Key, Value>&
110+
{
111+
MeshNode<Key, Value>::attach(m_self, m_key, other.get());
112+
return other;
113+
}
114+
115+
auto operator>>(Branch&& otherBranch) -> Branch&&
116+
{
117+
MeshNode<Key, Value>::attach(m_self, m_key, otherBranch.m_self);
118+
return std::move(otherBranch);
119+
}
120+
121+
auto operator-(MeshNodePtr<Key, Value>& other) -> void
122+
{
123+
MeshNode<Key, Value>::detach(m_self, m_key, other.get());
124+
}
125+
126+
auto operator&(const Branch& other) -> void
127+
{
128+
auto node1 = MeshNodePtr{m_self};
129+
auto node2 = MeshNodePtr{other.m_self};
130+
MeshNode<Key, Value>::attach(m_key, node1.get(), other.m_key, node2.get());
131+
}
132+
133+
auto operator/(const Branch& other) -> void
134+
{
135+
auto node1 = MeshNodePtr{m_self};
136+
auto node2 = MeshNodePtr{other.m_self};
137+
MeshNode<Key, Value>::detach(m_key, node1.get(), other.m_key, node2.get());
138+
139+
auto& node1SharedLocker = *node1.get();
140+
auto node1Accessor = node1SharedLocker.uniqueAccess();
141+
auto& node2SharedLocker = *node2.get();
142+
auto node2Accessor = node2SharedLocker.uniqueAccess();
143+
144+
auto& node2NetworkPtr = node2Accessor.value();
145+
node1Accessor.operator->()->detachChild(node2.get(), node2NetworkPtr);
146+
147+
auto& node1NetworkPtr = node1Accessor.value();
148+
node2Accessor.operator->()->detachChild(node1.get(), node1NetworkPtr);
149+
}
150+
151+
private:
152+
SharedPtr& m_self;
153+
const Key& m_key;
154+
};
155+
156+
[[nodiscard]] static auto makeRoot(auto&&... args) -> MeshNodePtr
157+
{
158+
return MeshNodePtr{NodePtr::makeRoot(std::forward<decltype(args)>(args)...)};
159+
}
160+
161+
[[nodiscard]] static auto make(auto&&... args) -> MeshNodePtr
162+
{
163+
return MeshNodePtr{NodePtr::make(std::forward<decltype(args)>(args)...)};
164+
}
165+
166+
MeshNodePtr(const SharedPtr& node): m_node(node) {}
167+
MeshNodePtr(SharedPtr&& node): m_node(std::move(node)) {}
168+
169+
[[nodiscard]] auto operator[](const Key& key) -> Branch
170+
{
171+
return Branch{m_node, key};
172+
}
173+
174+
[[nodiscard]] auto operator->()
175+
{
176+
return m_node.get();
177+
}
178+
179+
[[nodiscard]] auto operator*()
180+
{
181+
return *m_node;
182+
}
183+
184+
[[nodiscard]] auto get() -> SharedPtr&
185+
{
186+
return m_node;
187+
}
188+
189+
private:
190+
SharedPtr m_node;
191+
};
99192
}

tests/Container/MeshNetwork.mpp

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
88
inline auto _ = TestSuite{"Container/MeshNetwork", {"Container/NetworkPtr"}, [](auto& suite) {
99
using Logger = CppUtils::Logger<"CppUtils">;
1010
using StringMeshNode = CppUtils::Container::MeshNodePtr<std::string, std::string>;
11+
using Node = StringMeshNode::NodePtr::Value;
1112

1213
suite.addTest("Initialization", [&] {
1314
auto _ = StringMeshNode::make("banana");
@@ -22,12 +23,12 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
2223
});
2324

2425
suite.addTest("Copy reference", [&] {
25-
auto appleRef = CppUtils::Container::SafeShared<StringMeshNode>{};
26+
auto appleRef = std::optional<StringMeshNode>{};
2627
{
2728
auto apple = StringMeshNode::make("apple");
2829
appleRef = apple;
2930
}
30-
auto accessor = appleRef->sharedAccess();
31+
auto accessor = (*appleRef)->sharedAccess();
3132
const auto& value = accessor->value.value;
3233
Logger::print("{}\n", value);
3334
suite.expectEqual(value, "apple");
@@ -37,7 +38,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
3738
auto fruit = StringMeshNode::makeRoot("fruit");
3839
{
3940
auto apple = StringMeshNode::make("apple");
40-
StringMeshNode::Value::attach(fruit, "Elements", apple);
41+
Node::attach(fruit.get(), "Elements", apple.get());
4142
}
4243

4344
auto fruitAccessor = fruit->sharedAccess();
@@ -46,7 +47,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
4647
const auto& fruits = fruitBranches.at("Elements");
4748
suite.expectEqual(std::size(fruits), 1uz);
4849
{
49-
auto apple = StringMeshNode::SharedPtr{fruits[0]};
50+
auto apple = StringMeshNode::NodePtr::SharedPtr{fruits[0]};
5051
auto appleAccessor = apple->sharedAccess();
5152
const auto& value = appleAccessor->value.value;
5253
Logger::print("{}\n", value);
@@ -58,8 +59,8 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
5859
auto fruit = StringMeshNode::makeRoot("fruit");
5960
auto apple = StringMeshNode::make("apple");
6061
auto banana = StringMeshNode::make("banana");
61-
StringMeshNode::Value::attach(fruit, "Elements", apple);
62-
StringMeshNode::Value::attach(fruit, "Elements", banana);
62+
Node::attach(fruit.get(), "Elements", apple.get());
63+
Node::attach(fruit.get(), "Elements", banana.get());
6364

6465
{
6566
auto fruitAccessor = fruit->sharedAccess();
@@ -68,14 +69,14 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
6869
const auto& fruits = fruitBranches.at("Elements");
6970
suite.expectEqual(std::size(fruits), 2uz);
7071
{
71-
auto apple = StringMeshNode::SharedPtr{fruits[0]};
72+
auto apple = StringMeshNode::NodePtr::SharedPtr{fruits[0]};
7273
auto appleAccessor = apple->sharedAccess();
7374
const auto& value = appleAccessor->value.value;
7475
Logger::print("{}\n", value);
7576
suite.expectEqual(value, "apple");
7677
}
7778
{
78-
auto banana = StringMeshNode::SharedPtr{fruits[1]};
79+
auto banana = StringMeshNode::NodePtr::SharedPtr{fruits[1]};
7980
auto bananaAccessor = banana->sharedAccess();
8081
const auto& value = bananaAccessor->value.value;
8182
Logger::print("{}\n", value);
@@ -84,15 +85,15 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
8485
}
8586

8687
{
87-
StringMeshNode::Value::detach(fruit, "Elements", apple);
88+
Node::detach(fruit.get(), "Elements", apple.get());
8889

8990
auto fruitAccessor = fruit->sharedAccess();
9091
const auto& fruitBranches = fruitAccessor->value.branches;
9192
suite.expectEqual(std::size(fruitBranches), 1uz);
9293
const auto& fruits = fruitBranches.at("Elements");
9394
suite.expectEqual(std::size(fruits), 1uz);
9495
{
95-
auto banana = StringMeshNode::SharedPtr{fruits[0]};
96+
auto banana = StringMeshNode::NodePtr::SharedPtr{fruits[0]};
9697
auto bananaAccessor = banana->sharedAccess();
9798
const auto& value = bananaAccessor->value.value;
9899
Logger::print("{}\n", value);
@@ -101,7 +102,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
101102
}
102103

103104
{
104-
StringMeshNode::Value::detach(fruit, "Elements", banana);
105+
Node::detach(fruit.get(), "Elements", banana.get());
105106

106107
auto fruitAccessor = fruit->sharedAccess();
107108
const auto& fruitBranches = fruitAccessor->value.branches;
@@ -113,8 +114,8 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
113114
auto fruit = StringMeshNode::makeRoot("fruit");
114115
auto apple = StringMeshNode::make("apple");
115116
auto banana = StringMeshNode::make("banana");
116-
StringMeshNode::Value::attach(fruit, "Elements", apple);
117-
StringMeshNode::Value::attach(fruit, "Elements", banana);
117+
Node::attach(fruit.get(), "Elements", apple.get());
118+
Node::attach(fruit.get(), "Elements", banana.get());
118119

119120
{
120121
auto fruitAccessor = fruit->sharedAccess();
@@ -123,14 +124,14 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
123124
const auto& fruits = fruitBranches.at("Elements");
124125
suite.expectEqual(std::size(fruits), 2uz);
125126
{
126-
auto apple = StringMeshNode::SharedPtr{fruits[0]};
127+
auto apple = StringMeshNode::NodePtr::SharedPtr{fruits[0]};
127128
auto appleAccessor = apple->sharedAccess();
128129
const auto& value = appleAccessor->value.value;
129130
Logger::print("{}\n", value);
130131
suite.expectEqual(value, "apple");
131132
}
132133
{
133-
auto banana = StringMeshNode::SharedPtr{fruits[1]};
134+
auto banana = StringMeshNode::NodePtr::SharedPtr{fruits[1]};
134135
auto bananaAccessor = banana->sharedAccess();
135136
const auto& value = bananaAccessor->value.value;
136137
Logger::print("{}\n", value);
@@ -139,7 +140,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
139140
}
140141

141142
{
142-
StringMeshNode::Value::detach(fruit, "Elements");
143+
Node::detach(fruit.get(), "Elements");
143144

144145
auto fruitAccessor = fruit->sharedAccess();
145146
const auto& fruitBranches = fruitAccessor->value.branches;
@@ -151,8 +152,8 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
151152
auto elements = StringMeshNode::makeRoot("elements");
152153
auto orange = StringMeshNode::make("orange");
153154

154-
StringMeshNode::Value::attach(elements, "color", orange);
155-
StringMeshNode::Value::attach(elements, "fruit", orange);
155+
Node::attach(elements.get(), "color", orange.get());
156+
Node::attach(elements.get(), "fruit", orange.get());
156157
{
157158
auto elementAccessor = elements->sharedAccess();
158159
const auto& branches = elementAccessor->value.branches;
@@ -163,7 +164,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
163164
suite.expectEqual(orange->sharedAccess()->getDistanceFromRoot(), 1uz);
164165
}
165166

166-
StringMeshNode::Value::detach(elements, "color", orange);
167+
Node::detach(elements.get(), "color", orange.get());
167168
{
168169
auto elementAccessor = elements->sharedAccess();
169170
const auto& branches = elementAccessor->value.branches;
@@ -173,7 +174,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
173174
suite.expectEqual(orange->sharedAccess()->getDistanceFromRoot(), 1uz);
174175
}
175176

176-
StringMeshNode::Value::detach(elements, "fruit", orange);
177+
Node::detach(elements.get(), "fruit", orange.get());
177178
{
178179
auto elementAccessor = elements->sharedAccess();
179180
const auto& branches = elementAccessor->value.branches;
@@ -186,13 +187,13 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
186187
suite.addTest("Bilateral attachment", [&] {
187188
auto fruit = StringMeshNode::makeRoot("fruit");
188189
auto apple = StringMeshNode::make("apple");
189-
StringMeshNode::Value::attach("Categories", fruit, "Elements", apple);
190+
Node::attach("Categories", fruit.get(), "Elements", apple.get());
190191
{
191192
auto fruitAccessor = fruit->sharedAccess();
192193
const auto& fruitBranches = fruitAccessor->value.branches;
193194
const auto& fruits = fruitBranches.at("Elements");
194195
suite.expectEqual(std::size(fruits), 1uz);
195-
auto firstFruit = StringMeshNode::SharedPtr{fruits[0]};
196+
auto firstFruit = StringMeshNode::NodePtr::SharedPtr{fruits[0]};
196197
auto appleAccessor = firstFruit->sharedAccess();
197198
const auto& appleName = appleAccessor->value.value;
198199
const auto& fruitName = fruitAccessor->value.value;
@@ -205,7 +206,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
205206
const auto& appleBranches = appleAccessor->value.branches;
206207
const auto& appleCategories = appleBranches.at("Categories");
207208
suite.expect(std::size(appleCategories) == 1);
208-
auto firstCategory = StringMeshNode::SharedPtr{appleCategories[0]};
209+
auto firstCategory = StringMeshNode::NodePtr::SharedPtr{appleCategories[0]};
209210
auto fruitAccessor = firstCategory->sharedAccess();
210211
const auto& appleName = appleAccessor->value.value;
211212
const auto& fruitName = fruitAccessor->value.value;
@@ -218,13 +219,13 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
218219
suite.addTest("Bilateral attachment (reverse order)", [&] {
219220
auto fruit = StringMeshNode::makeRoot("fruit");
220221
auto apple = StringMeshNode::make("apple");
221-
StringMeshNode::Value::attach("Elements", apple, "Categories", fruit);
222+
Node::attach("Elements", apple.get(), "Categories", fruit.get());
222223
{
223224
auto fruitAccessor = fruit->sharedAccess();
224225
const auto& fruitBranches = fruitAccessor->value.branches;
225226
const auto& fruits = fruitBranches.at("Elements");
226227
suite.expectEqual(std::size(fruits), 1uz);
227-
auto firstFruit = StringMeshNode::SharedPtr{fruits[0]};
228+
auto firstFruit = StringMeshNode::NodePtr::SharedPtr{fruits[0]};
228229
auto appleAccessor = firstFruit->sharedAccess();
229230
const auto& appleName = appleAccessor->value.value;
230231
const auto& fruitName = fruitAccessor->value.value;
@@ -237,7 +238,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
237238
const auto& appleBranches = appleAccessor->value.branches;
238239
const auto& appleCategories = appleBranches.at("Categories");
239240
suite.expect(std::size(appleCategories) == 1);
240-
auto firstCategory = StringMeshNode::SharedPtr{appleCategories[0]};
241+
auto firstCategory = StringMeshNode::NodePtr::SharedPtr{appleCategories[0]};
241242
auto fruitAccessor = firstCategory->sharedAccess();
242243
const auto& appleName = appleAccessor->value.value;
243244
const auto& fruitName = fruitAccessor->value.value;
@@ -253,39 +254,39 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
253254
auto orangeFruit = StringMeshNode::make("orange");
254255
auto lemon = StringMeshNode::make("lemon");
255256

256-
StringMeshNode::Value::attach("Categories", fruit, "Elements", banana);
257-
StringMeshNode::Value::attach("Categories", fruit, "Elements", orangeFruit);
258-
StringMeshNode::Value::attach("Categories", fruit, "Elements", lemon);
257+
Node::attach("Categories", fruit.get(), "Elements", banana.get());
258+
Node::attach("Categories", fruit.get(), "Elements", orangeFruit.get());
259+
Node::attach("Categories", fruit.get(), "Elements", lemon.get());
259260

260261
auto color = StringMeshNode::makeRoot("color");
261262
auto orangeColor = StringMeshNode::make("orange");
262263
auto yellow = StringMeshNode::make("yellow");
263264

264-
StringMeshNode::Value::attach("Categories", color, "Elements", orangeColor);
265-
StringMeshNode::Value::attach("Categories", color, "Elements", yellow);
265+
Node::attach("Categories", color.get(), "Elements", orangeColor.get());
266+
Node::attach("Categories", color.get(), "Elements", yellow.get());
266267

267-
StringMeshNode::Value::attach("Elements", banana, "Colors", yellow);
268-
StringMeshNode::Value::attach("Elements", orangeFruit, "Colors", orangeColor);
269-
StringMeshNode::Value::attach("Elements", lemon, "Colors", yellow);
268+
Node::attach("Elements", banana.get(), "Colors", yellow.get());
269+
Node::attach("Elements", orangeFruit.get(), "Colors", orangeColor.get());
270+
Node::attach("Elements", lemon.get(), "Colors", yellow.get());
270271

271272
{
272273
auto fruitAccessor = fruit->sharedAccess();
273274
const auto& fruitBranches = fruitAccessor->value.branches;
274275
for (const auto& weakFruit : fruitBranches.at("Elements"))
275276
{
276-
auto fruit = StringMeshNode::SharedPtr{weakFruit};
277+
auto fruit = StringMeshNode::NodePtr::SharedPtr{weakFruit};
277278
auto fruitAccessor = fruit->sharedAccess();
278279
const auto& fruitBranches = fruitAccessor->value.branches;
279280

280281
const auto& fruitCategories = fruitBranches.at("Categories");
281282
suite.expect(std::size(fruitCategories) == 1);
282-
auto fruitCategory = StringMeshNode::SharedPtr{fruitCategories[0]};
283+
auto fruitCategory = StringMeshNode::NodePtr::SharedPtr{fruitCategories[0]};
283284
auto fruitCategoryAccessor = fruitCategory->sharedAccess();
284285
suite.expectEqual(fruitCategoryAccessor->value.value, "fruit");
285286

286287
const auto& colors = fruitBranches.at("Colors");
287288
suite.expect(std::size(colors) == 1);
288-
auto color = StringMeshNode::SharedPtr{colors[0]};
289+
auto color = StringMeshNode::NodePtr::SharedPtr{colors[0]};
289290
auto colorAccessor = color->sharedAccess();
290291

291292
Logger::print("{} is a {} {}\n", fruitAccessor->value.value, colorAccessor->value.value, fruitCategoryAccessor->value.value);

0 commit comments

Comments
 (0)