Skip to content

Commit fb6d27d

Browse files
committed
Container/MeshNodePtr: getValue, getBranch, getBranches
1 parent 1c6640f commit fb6d27d

2 files changed

Lines changed: 165 additions & 23 deletions

File tree

modules/Container/MeshNetwork.mpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,57 @@ export namespace CppUtils::Container
192192
return (self.m_node);
193193
}
194194

195+
[[nodiscard]] auto getValue() const -> std::expected<Value, std::string_view>
196+
{
197+
using namespace std::literals;
198+
199+
if (not m_node)
200+
return std::unexpected{"Invalid MeshNodePtr"sv};
201+
auto sharedLocker = m_node->sharedAccess();
202+
return sharedLocker->value.value;
203+
}
204+
205+
[[nodiscard]] auto getBranch(const Key& key, std::size_t index = 0) const -> std::expected<MeshNodePtr, std::string_view>
206+
{
207+
using namespace std::literals;
208+
209+
if (not m_node)
210+
return std::unexpected{"Invalid MeshNodePtr"sv};
211+
auto sharedLocker = m_node->sharedAccess();
212+
const auto& branches = sharedLocker->value.branches;
213+
if (auto it = branches.find(key); it != std::cend(branches))
214+
{
215+
const auto& children = it->second;
216+
if (index < std::size(children))
217+
if (auto sharedChild = children[index].lock())
218+
return MeshNodePtr{sharedChild};
219+
else
220+
return std::unexpected{"Failed to lock weak pointer for branch. Node might have been deleted"sv};
221+
else
222+
return std::unexpected{"Branch index out of bounds"sv};
223+
}
224+
return std::unexpected{"Branch key not found"sv};
225+
}
226+
227+
[[nodiscard]] auto getBranches(const Key& key) const -> std::expected<std::vector<MeshNodePtr>, std::string_view>
228+
{
229+
using namespace std::literals;
230+
231+
if (not m_node)
232+
return std::unexpected{"Invalid MeshNodePtr"sv};
233+
auto sharedLocker = m_node->sharedAccess();
234+
const auto& branches = sharedLocker->value.branches;
235+
if (auto it = branches.find(key); it != std::cend(branches))
236+
{
237+
auto result = std::vector<MeshNodePtr>{};
238+
for (const auto& weakChild : it->second)
239+
if (auto sharedChild = weakChild.lock())
240+
result.emplace_back(sharedChild);
241+
return result;
242+
}
243+
return std::unexpected{"Branch key not found"sv};
244+
}
245+
195246
private:
196247
SharedPtr m_node = nullptr;
197248
};

tests/Container/MeshNetwork.mpp

Lines changed: 114 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import CppUtils;
66
export namespace CppUtils::UnitTest::Container::MeshNetwork
77
{
88
inline auto _ = TestSuite{"Container/MeshNetwork", {"Container/NetworkPtr"}, [](auto& suite) {
9+
using namespace std::literals;
910
using Logger = CppUtils::Logger<"CppUtils">;
1011
using StringMeshNodePtr = CppUtils::Container::MeshNodePtr<std::string, std::string>;
1112
using Node = StringMeshNodePtr::NetworkPtr::Value;
@@ -152,34 +153,34 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
152153
auto elements = StringMeshNodePtr::makeRoot("elements");
153154
auto orange = StringMeshNodePtr::make("orange");
154155

155-
Node::attach(elements.get(), "color", orange.get());
156-
Node::attach(elements.get(), "fruit", orange.get());
156+
Node::attach(elements.get(), "Color", orange.get());
157+
Node::attach(elements.get(), "Fruit", orange.get());
157158
{
158159
auto elementAccessor = elements->sharedAccess();
159160
const auto& branches = elementAccessor->value.branches;
160-
suite.expectEqual(branches.count("color"), 1uz);
161-
suite.expectEqual(branches.count("fruit"), 1uz);
162-
suite.expectEqual(std::size(branches.at("color")), 1uz);
163-
suite.expectEqual(std::size(branches.at("fruit")), 1uz);
161+
suite.expectEqual(branches.count("Color"), 1uz);
162+
suite.expectEqual(branches.count("Fruit"), 1uz);
163+
suite.expectEqual(std::size(branches.at("Color")), 1uz);
164+
suite.expectEqual(std::size(branches.at("Fruit")), 1uz);
164165
suite.expectEqual(orange->sharedAccess()->getDistanceFromRoot(), 1uz);
165166
}
166167

167-
Node::detach(elements.get(), "color", orange.get());
168+
Node::detach(elements.get(), "Color", orange.get());
168169
{
169170
auto elementAccessor = elements->sharedAccess();
170171
const auto& branches = elementAccessor->value.branches;
171-
suite.expectEqual(branches.count("color"), 0uz);
172-
suite.expectEqual(branches.count("fruit"), 1uz);
173-
suite.expectEqual(std::size(branches.at("fruit")), 1uz);
172+
suite.expectEqual(branches.count("Color"), 0uz);
173+
suite.expectEqual(branches.count("Fruit"), 1uz);
174+
suite.expectEqual(std::size(branches.at("Fruit")), 1uz);
174175
suite.expectEqual(orange->sharedAccess()->getDistanceFromRoot(), 1uz);
175176
}
176177

177-
Node::detach(elements.get(), "fruit", orange.get());
178+
Node::detach(elements.get(), "Fruit", orange.get());
178179
{
179180
auto elementAccessor = elements->sharedAccess();
180181
const auto& branches = elementAccessor->value.branches;
181-
suite.expectEqual(branches.count("color"), 0uz);
182-
suite.expectEqual(branches.count("fruit"), 0uz);
182+
suite.expectEqual(branches.count("Color"), 0uz);
183+
suite.expectEqual(branches.count("Fruit"), 0uz);
183184
suite.expectEqual(orange->sharedAccess()->getDistanceFromRoot(), std::numeric_limits<std::size_t>::max());
184185
}
185186
});
@@ -298,12 +299,12 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
298299
auto root = StringMeshNodePtr::makeRoot("root");
299300
auto child = StringMeshNodePtr::make("child");
300301

301-
root["branch"] >> child;
302+
root["Branch"] >> child;
302303

303304
auto rootAccessor = root->sharedAccess();
304305
const auto& branches = rootAccessor->value.branches;
305306
suite.expectEqual(std::size(branches), 1uz);
306-
const auto& children = branches.at("branch");
307+
const auto& children = branches.at("Branch");
307308
suite.expectEqual(std::size(children), 1uz);
308309
auto childAccessor = child->sharedAccess();
309310
suite.expectEqual(childAccessor->getDistanceFromRoot(), 1uz);
@@ -314,7 +315,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
314315
auto child1 = StringMeshNodePtr::make("child1");
315316
auto child2 = StringMeshNodePtr::make("child2");
316317

317-
root["branch1"] >> child1["branch2"] >> child2;
318+
root["Branch1"] >> child1["Branch2"] >> child2;
318319

319320
auto rootAccessor = root->sharedAccess();
320321
const auto& rootBranches = rootAccessor->value.branches;
@@ -328,8 +329,8 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
328329
auto root = StringMeshNodePtr::makeRoot("root");
329330
auto child = StringMeshNodePtr::make("child");
330331

331-
root["branch"] >> child;
332-
root["branch"] - child;
332+
root["Branch"] >> child;
333+
root["Branch"] - child;
333334

334335
auto rootAccessor = root->sharedAccess();
335336
const auto& branches = rootAccessor->value.branches;
@@ -340,26 +341,26 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
340341
auto fruit = StringMeshNodePtr::makeRoot("fruit");
341342
auto apple = StringMeshNodePtr::make("apple");
342343

343-
fruit["elements"] & apple["category"];
344+
fruit["Elements"] & apple["Category"];
344345
{
345346
auto fruitAccessor = fruit->sharedAccess();
346347
const auto& fruitBranches = fruitAccessor->value.branches;
347348
suite.expectEqual(std::size(fruitBranches), 1uz);
348-
suite.expectEqual(std::size(fruitBranches.at("category")), 1uz);
349+
suite.expectEqual(std::size(fruitBranches.at("Category")), 1uz);
349350

350351
auto appleAccessor = apple->sharedAccess();
351352
const auto& appleBranches = appleAccessor->value.branches;
352353
suite.expectEqual(std::size(appleBranches), 1uz);
353-
suite.expectEqual(std::size(appleBranches.at("elements")), 1uz);
354+
suite.expectEqual(std::size(appleBranches.at("Elements")), 1uz);
354355
}
355356
});
356357

357358
suite.addTest("Bidirectional unlink (operator/)", [&] {
358359
auto fruit = StringMeshNodePtr::makeRoot("fruit");
359360
auto apple = StringMeshNodePtr::make("apple");
360361

361-
fruit["elements"] & apple["category"];
362-
fruit["elements"] / apple["category"];
362+
fruit["Elements"] & apple["Category"];
363+
fruit["Elements"] / apple["Category"];
363364
{
364365
auto fruitAccessor = fruit->sharedAccess();
365366
const auto& fruitBranches = fruitAccessor->value.branches;
@@ -369,5 +370,95 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
369370
suite.expect(std::empty(appleBranches));
370371
}
371372
});
373+
374+
suite.addTest("Get value", [&] {
375+
auto node = StringMeshNodePtr::make("value");
376+
auto expectedValue = node.getValue();
377+
suite.expect(expectedValue.has_value());
378+
suite.expectEqual(expectedValue.value(), "value");
379+
});
380+
381+
suite.addTest("Get value: Invalid node", [&] {
382+
auto emptyNode = StringMeshNodePtr{};
383+
auto unexpectedValue = emptyNode.getValue();
384+
suite.expect(not unexpectedValue.has_value());
385+
suite.expectEqual(unexpectedValue.error(), "Invalid MeshNodePtr"sv);
386+
});
387+
388+
suite.addTest("Get branch", [&] {
389+
auto root = StringMeshNodePtr::makeRoot("root");
390+
auto child = StringMeshNodePtr::make("child");
391+
root["Children"] >> child;
392+
393+
auto childExpected = root.getBranch("Children", 0);
394+
395+
suite.expect(childExpected.has_value());
396+
suite.expectEqual(childExpected.value().getValue().value(), "child");
397+
});
398+
399+
suite.addTest("Get branch: Non-existent branch", [&] {
400+
auto root = StringMeshNodePtr::makeRoot("root");
401+
auto child = StringMeshNodePtr::make("child");
402+
root["Children"] >> child;
403+
404+
auto invalidKeyExpected = root.getBranch("NonExistentBranch");
405+
406+
suite.expect(not invalidKeyExpected.has_value());
407+
suite.expectEqual(invalidKeyExpected.error(), "Branch key not found"sv);
408+
});
409+
410+
suite.addTest("Get branch: Invalid index", [&] {
411+
auto root = StringMeshNodePtr::makeRoot("root");
412+
auto child = StringMeshNodePtr::make("child");
413+
root["Children"] >> child;
414+
415+
auto invalidIndexExpected = root.getBranch("Children", 1);
416+
417+
suite.expect(not invalidIndexExpected.has_value());
418+
suite.expectEqual(invalidIndexExpected.error(), "Branch index out of bounds"sv);
419+
});
420+
421+
suite.addTest("Get branch: Invalid node", [&] {
422+
auto emptyNode = StringMeshNodePtr{};
423+
424+
auto emptyBranchExpected = emptyNode.getBranch("Branch");
425+
426+
suite.expect(not emptyBranchExpected.has_value());
427+
suite.expectEqual(emptyBranchExpected.error(), "Invalid MeshNodePtr"sv);
428+
});
429+
430+
suite.addTest("Get branches", [&] {
431+
auto root = StringMeshNodePtr::makeRoot("root");
432+
auto child1 = StringMeshNodePtr::make("child1");
433+
auto child2 = StringMeshNodePtr::make("child2");
434+
root["Branch"] >> child1;
435+
root["Branch"] >> child2;
436+
437+
auto expectedChildren = root.getBranches("Branch");
438+
439+
suite.expect(expectedChildren.has_value());
440+
auto children = expectedChildren.value();
441+
suite.expectEqual(std::size(children), 2uz);
442+
suite.expectEqual(children[0].getValue().value(), "child1");
443+
suite.expectEqual(children[1].getValue().value(), "child2");
444+
});
445+
446+
suite.addTest("Get branches: Non-existent branch", [&] {
447+
auto root = StringMeshNodePtr::makeRoot("root");
448+
449+
auto expectedNonExistent = root.getBranches("NonExistentBranch");
450+
451+
suite.expect(not expectedNonExistent.has_value());
452+
suite.expectEqual(expectedNonExistent.error(), "Branch key not found"sv);
453+
});
454+
455+
suite.addTest("Get branches: Invalid node", [&] {
456+
auto emptyNode = StringMeshNodePtr{};
457+
458+
auto result = emptyNode.getBranches("Branch");
459+
460+
suite.expect(not result.has_value());
461+
suite.expectEqual(result.error(), "Invalid MeshNodePtr"sv);
462+
});
372463
}};
373464
}

0 commit comments

Comments
 (0)