From f60a24e07da1b9948262ef0dc2f0a8ba33b8d569 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 15 Feb 2022 15:55:12 -0800 Subject: [PATCH] Add support for Range-based DomPrefixTree construction, fix initializer_list Signed-off-by: Nicholas Van Sickle --- .../AzCore/AzCore/DOM/DomPrefixTree.h | 22 +++++++++++++++--- .../AzCore/AzCore/DOM/DomPrefixTree.inl | 16 +++++++------ .../AzCore/Tests/DOM/DomPrefixTreeTests.cpp | 23 +++++++++++++++++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.h b/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.h index 1322dbf843..4349783b8c 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.h @@ -9,9 +9,10 @@ #pragma once #include -#include #include +#include #include +#include namespace AZ::Dom { @@ -42,6 +43,19 @@ namespace AZ::Dom DomPrefixTree(const DomPrefixTree&) = default; DomPrefixTree(DomPrefixTree&&) = default; explicit DomPrefixTree(AZStd::initializer_list> init); + template< + class Range, + class = AZStd::enable_if_t< + AZStd::ranges::input_range && + AZStd::convertible_to>, Path> && + AZStd::convertible_to>, T>>> + explicit DomPrefixTree(Range&& range) + { + for (auto&& [path, value] : AZStd::forward(range)) + { + SetValue(path, value); + } + } DomPrefixTree& operator=(const DomPrefixTree&) = default; DomPrefixTree& operator=(DomPrefixTree&&) = default; @@ -55,10 +69,12 @@ namespace AZ::Dom //! \see ValueAtPath const T* ValueAtPath(const Path& path, PrefixTreeMatch match) const; //! Visits a path and returns the most specific matching value or some default value. - T ValueAtPathOrDefault(const Path& path, T&& defaultValue, PrefixTreeMatch match) const; + template + T ValueAtPathOrDefault(const Path& path, Deduced&& defaultValue, PrefixTreeMatch match) const; //! Sets the value stored at path. - void SetValue(const Path& path, T&& value); + template + void SetValue(const Path& path, Deduced&& value); //! Removes the value stored at path. If removeChildren is true, also removes any values stored at subpaths. void EraseValue(const Path& path, bool removedChildren = false); //! Removes all entries from this tree. diff --git a/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.inl b/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.inl index be129aa3e0..ea8745413c 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.inl +++ b/Code/Framework/AzCore/AzCore/DOM/DomPrefixTree.inl @@ -13,9 +13,9 @@ namespace AZ::Dom template DomPrefixTree::DomPrefixTree(AZStd::initializer_list> init) { - for (const auto& entry : init) + for (const auto& [path, value] : init) { - SetValue(entry.first, entry.second); + SetValue(path, value); } } @@ -158,7 +158,7 @@ namespace AZ::Dom return result; } - template + template const T* DomPrefixTree::ValueAtPath(const Path& path, PrefixTreeMatch match) const { // Const coerce the ValueAtPath result, which doesn't mutate but returns a mutable pointer @@ -166,14 +166,16 @@ namespace AZ::Dom } template - T DomPrefixTree::ValueAtPathOrDefault(const Path& path, T&& defaultValue, PrefixTreeMatch match) const + template + T DomPrefixTree::ValueAtPathOrDefault(const Path& path, Deduced&& defaultValue, PrefixTreeMatch match) const { const T* value = ValueAtPath(path, match); - return value == nullptr ? AZStd::forward(defaultValue) : *value; + return value == nullptr ? AZStd::forward(defaultValue) : *value; } template - void DomPrefixTree::SetValue(const Path& path, T&& value) + template + void DomPrefixTree::SetValue(const Path& path, Deduced&& value) { Node* node = &m_rootNode; for (const PathEntry& entry : path) @@ -181,7 +183,7 @@ namespace AZ::Dom // Get or create an entry in this node node = &node->m_values[entry]; } - node->m_data = AZStd::forward(value); + node->m_data = AZStd::forward(value); } template diff --git a/Code/Framework/AzCore/Tests/DOM/DomPrefixTreeTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomPrefixTreeTests.cpp index 49496b44f8..e79c18aa72 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomPrefixTreeTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomPrefixTreeTests.cpp @@ -13,6 +13,29 @@ namespace AZ::Dom::Tests { using DomPrefixTreeTests = DomTestFixture; + TEST_F(DomPrefixTreeTests, InitializeFromInitializerList) + { + DomPrefixTree tree({ + { Path(), 0 }, + { Path("/foo/bar"), 1 }, + }); + + EXPECT_EQ(0, *tree.ValueAtPath(Path(), PrefixTreeMatch::ExactPath)); + EXPECT_EQ(1, *tree.ValueAtPath(Path("/foo/bar"), PrefixTreeMatch::ExactPath)); + } + + TEST_F(DomPrefixTreeTests, InitializeFromRange) + { + AZStd::vector> container({ + { Path(), 21 }, + { Path("/foo/bar"), 42 }, + }); + DomPrefixTree tree(container); + + EXPECT_EQ(21, *tree.ValueAtPath(Path(), PrefixTreeMatch::ExactPath)); + EXPECT_EQ(42, *tree.ValueAtPath(Path("/foo/bar"), PrefixTreeMatch::ExactPath)); + } + TEST_F(DomPrefixTreeTests, GetAndSetRoot) { DomPrefixTree tree;