Skip to content

Commit d25881d

Browse files
committed
Container/MeshNodePtr/Branch: BranchIterator
1 parent 29e2f35 commit d25881d

2 files changed

Lines changed: 78 additions & 30 deletions

File tree

modules/Container/MeshNetwork.mpp

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ export namespace CppUtils::Container
104104
class Branch final
105105
{
106106
public:
107-
Branch(SharedPtr& self, const Key& key): m_self(self), m_key(key) {}
107+
using ChildrenVector = std::vector<typename MeshNode<Key, Value>::WeakPtr>;
108+
109+
Branch(SharedPtr& self, const Key& key, ChildrenVector children): m_self(self), m_key(key), m_children(std::move(children)) {}
108110

109111
auto operator>>(MeshNodePtr<Key, Value>& other) -> MeshNodePtr<Key, Value>&
110112
{
@@ -170,9 +172,65 @@ export namespace CppUtils::Container
170172
return std::unexpected{"Branch key not found"sv};
171173
}
172174

175+
class BranchIterator final
176+
{
177+
public:
178+
using iterator_category = std::input_iterator_tag;
179+
using value_type = MeshNodePtr<Key, Value>;
180+
using difference_type = std::ptrdiff_t;
181+
using pointer = value_type*;
182+
using reference = value_type&;
183+
using internal_iterator_type = std::vector<typename MeshNode<Key, Value>::WeakPtr>::const_iterator;
184+
185+
BranchIterator() = default;
186+
BranchIterator(internal_iterator_type iterator): m_iterator{iterator} {}
187+
188+
[[nodiscard]] auto operator*() const -> MeshNodePtr<Key, Value>
189+
{
190+
return MeshNodePtr<Key, Value>{m_iterator->lock()};
191+
}
192+
193+
auto operator++() -> BranchIterator&
194+
{
195+
++m_iterator;
196+
return *this;
197+
}
198+
199+
auto operator++(int) -> BranchIterator
200+
{
201+
BranchIterator temp = *this;
202+
++(*this);
203+
return temp;
204+
}
205+
206+
[[nodiscard]] auto operator==(const BranchIterator& other) const -> bool
207+
{
208+
return m_iterator == other.m_iterator;
209+
}
210+
211+
[[nodiscard]] auto operator!=(const BranchIterator& other) const -> bool
212+
{
213+
return !(*this == other);
214+
}
215+
216+
private:
217+
internal_iterator_type m_iterator;
218+
};
219+
220+
[[nodiscard]] auto begin() const -> BranchIterator
221+
{
222+
return BranchIterator{std::cbegin(m_children)};
223+
}
224+
225+
[[nodiscard]] auto end() const -> BranchIterator
226+
{
227+
return BranchIterator{std::cend(m_children)};
228+
}
229+
173230
private:
174231
SharedPtr& m_self;
175232
const Key& m_key;
233+
ChildrenVector m_children;
176234
};
177235

178236
[[nodiscard]] static auto makeRoot(auto&&... args) -> MeshNodePtr
@@ -196,7 +254,14 @@ export namespace CppUtils::Container
196254

197255
[[nodiscard]] auto operator[](const Key& key) -> Branch
198256
{
199-
return Branch{m_node, key};
257+
if (not m_node)
258+
return Branch{m_node, key, {}};
259+
260+
auto sharedLocker = m_node->sharedAccess();
261+
const auto& branches = sharedLocker->value.branches;
262+
if (auto iterator = branches.find(key); iterator != std::cend(branches))
263+
return Branch{m_node, key, iterator->second};
264+
return Branch{m_node, key, {}};
200265
}
201266

202267
[[nodiscard]] auto operator->(this auto&& self)
@@ -224,25 +289,6 @@ export namespace CppUtils::Container
224289
return sharedLocker->value.value;
225290
}
226291

227-
[[nodiscard]] auto getNodes(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-
246292
private:
247293
SharedPtr m_node = nullptr;
248294
};

tests/Container/MeshNetwork.mpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,10 +434,10 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
434434
root["Branch"] >> child1;
435435
root["Branch"] >> child2;
436436

437-
auto expectedChildren = root.getNodes("Branch");
437+
auto children = std::vector<StringMeshNodePtr>{};
438+
for (const auto& child : root["Branch"])
439+
children.push_back(child);
438440

439-
suite.expect(expectedChildren.has_value());
440-
auto children = expectedChildren.value();
441441
suite.expectEqual(std::size(children), 2uz);
442442
suite.expectEqual(children[0].getValue().value(), "child1");
443443
suite.expectEqual(children[1].getValue().value(), "child2");
@@ -446,19 +446,21 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
446446
suite.addTest("Get nodes: Non-existent branch", [&] {
447447
auto root = StringMeshNodePtr::makeRoot("root");
448448

449-
auto expectedNonExistent = root.getNodes("NonExistentBranch");
449+
auto children = std::vector<StringMeshNodePtr>{};
450+
for (const auto& child : root["NonExistentBranch"])
451+
children.push_back(child);
450452

451-
suite.expect(not expectedNonExistent.has_value());
452-
suite.expectEqual(expectedNonExistent.error(), "Branch key not found"sv);
453+
suite.expect(std::empty(children));
453454
});
454455

455456
suite.addTest("Get nodes: Invalid node", [&] {
456457
auto emptyNode = StringMeshNodePtr{};
457458

458-
auto result = emptyNode.getNodes("Branch");
459+
auto children = std::vector<StringMeshNodePtr>{};
460+
for (const auto& child : emptyNode["Branch"])
461+
children.push_back(child);
459462

460-
suite.expect(not result.has_value());
461-
suite.expectEqual(result.error(), "Invalid MeshNodePtr"sv);
463+
suite.expect(std::empty(children));
462464
});
463465
}};
464466
}

0 commit comments

Comments
 (0)