diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 14:53:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 14:53:22 +0000 |
commit | 52c021ee0b0c6ad2128ed550c694aad0d11d4c3f (patch) | |
tree | 83cf8627b94336cf4bee7479b9749263bbfd3a06 /src/lib/testutils/user_context_utils.cc | |
parent | Initial commit. (diff) | |
download | isc-kea-upstream.tar.xz isc-kea-upstream.zip |
Adding upstream version 2.5.7.upstream/2.5.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/testutils/user_context_utils.cc')
-rw-r--r-- | src/lib/testutils/user_context_utils.cc | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/lib/testutils/user_context_utils.cc b/src/lib/testutils/user_context_utils.cc new file mode 100644 index 0000000..30e9c3e --- /dev/null +++ b/src/lib/testutils/user_context_utils.cc @@ -0,0 +1,136 @@ +// Copyright (C) 2017-2024 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <testutils/user_context_utils.h> + +using namespace isc::data; + +namespace { + +/// @brief Encapsulate either a modified copy or a unmodified value +/// @tparam EP ElementPtr or ConstElementPtr (compiler can't infer which one) +template<typename EP> +class Value { +public: + /// @brief Factory for modified copy + static Value mkCopy(EP value) { return (Value(value, false)); } + + /// @brief Factory for unmodified original + static Value mkShare(EP value) { return (Value(value, true)); } + + /// @brief Get the value + /// @return the value + EP get() const { return (value_); } + + /// @brief Get the shared status + /// @return true if original, false if copy + bool isShared() const { return (shared_); } + +private: + /// @brief Constructor + /// @param value the modified copy or unmodified value + /// @param shared true if original, false if copy + Value(EP value, bool shared) : value_(value), shared_(shared) { } + + /// @brief the value + EP value_; + + /// @brief the shared status + bool shared_; +}; + +/// @brief Recursive helper +/// +/// @tparam EP ElementPtr or ConstElementPtr (compiler will infer which one) +/// @param element the element to traverse +/// @return a modified copy where comment entries were moved to user-context +/// or the unmodified original argument encapsulated into a Value +template<typename EP> +Value<EP> moveComments1(EP element) { + bool modified = false; + + // On lists recurse on items + if (element->getType() == Element::list) { + ElementPtr result = ElementPtr(new ListElement()); + typedef std::vector<ElementPtr> ListType; + const ListType& list = element->listValue(); + for (auto const& it : list) { + Value<ElementPtr> item = moveComments1(it); + result->add(item.get()); + if (!item.isShared()) { + modified = true; + } + } + if (!modified) { + return (Value<EP>::mkShare(element)); + } else { + return (Value<EP>::mkCopy(result)); + } + } else if (element->getType() != Element::map) { + return (Value<EP>::mkShare(element)); + } + + // Process maps: recurse on items + ElementPtr result = ElementPtr(new MapElement()); + bool has_comment = false; + typedef std::map<std::string, ConstElementPtr> map_type; + const map_type& map = element->mapValue(); + for (auto const& it : map) { + if (it.first == "comment") { + // Note there is a comment entry to move + has_comment = true; + } else if (it.first == "user-context") { + // Do not traverse user-context entries + result->set("user-context", it.second); + } else { + // Not comment or user-context + Value<ConstElementPtr> item = moveComments1(it.second); + result->set(it.first, item.get()); + if (!item.isShared()) { + modified = true; + } + } + } + // Check if the value should be not modified + if (!has_comment && !modified) { + return (Value<EP>::mkShare(element)); + } + + if (has_comment) { + // Move the comment entry + ConstElementPtr comment = element->get("comment"); + ElementPtr moved = Element::createMap(); + moved->set("comment", comment); + ConstElementPtr previous = element->get("user-context"); + // If there is already a user context merge it + if (previous) { + merge(moved, previous); + } + result->set("user-context", moved); + } + + return (Value<EP>::mkCopy(result)); +} + +} // anonymous namespace + +namespace isc { +namespace test { + +ElementPtr moveComments(ElementPtr element) { + Value<ElementPtr> result = moveComments1(element); + return (result.get()); +} + +ConstElementPtr moveComments(ConstElementPtr element) { + Value<ConstElementPtr> result = moveComments1(element); + return (result.get()); +} + +} // end of isc::test namespace +} // end of isc namespace |