Kea 1.5.0
user_context_utils.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10
11using namespace isc::data;
12
13namespace {
14
17template<typename EP>
18class Value {
19public:
21 static Value mkCopy(EP value) { return (Value(value, false)); }
22
24 static Value mkShare(EP value) { return (Value(value, true)); }
25
28 EP get() const { return (value_); }
29
32 bool isShared() const { return (shared_); }
33
34private:
38 Value(EP value, bool shared) : value_(value), shared_(shared) { }
39
41 EP value_;
42
44 bool shared_;
45};
46
53template<typename EP>
54Value<EP> moveComments1(EP element) {
55 bool modified = false;
56
57 // On lists recurse on items
58 if (element->getType() == Element::list) {
59 ElementPtr result = ElementPtr(new ListElement());
60 typedef std::vector<ElementPtr> ListType;
61 const ListType& list = element->listValue();
62 for (ListType::const_iterator it = list.cbegin();
63 it != list.cend(); ++it) {
64 Value<ElementPtr> item = moveComments1(*it);
65 result->add(item.get());
66 if (!item.isShared()) {
67 modified = true;
68 }
69 }
70 if (!modified) {
71 return (Value<EP>::mkShare(element));
72 } else {
73 return (Value<EP>::mkCopy(result));
74 }
75 } else if (element->getType() != Element::map) {
76 return (Value<EP>::mkShare(element));
77 }
78
79 // Process maps: recurse on items
80 ElementPtr result = ElementPtr(new MapElement());
81 bool has_comment = false;
82 typedef std::map<std::string, ConstElementPtr> map_type;
83 const map_type& map = element->mapValue();
84 for (map_type::const_iterator it = map.cbegin(); it != map.cend(); ++it) {
85 if (it->first == "comment") {
86 // Note there is a comment entry to move
87 has_comment = true;
88 } else if (it->first == "user-context") {
89 // Do not traverse user-context entries
90 result->set("user-context", it->second);
91 } else {
92 // Not comment or user-context
93 Value<ConstElementPtr> item = moveComments1(it->second);
94 result->set(it->first, item.get());
95 if (!item.isShared()) {
96 modified = true;
97 }
98 }
99 }
100 // Check if the value should be not modified
101 if (!has_comment && !modified) {
102 return (Value<EP>::mkShare(element));
103 }
104
105 if (has_comment) {
106 // Move the comment entry
107 ConstElementPtr comment = element->get("comment");
109 moved->set("comment", comment);
110 ConstElementPtr previous = element->get("user-context");
111 // If there is already a user context merge it
112 if (previous) {
113 merge(moved, previous);
114 }
115 result->set("user-context", moved);
116 }
117
118 return (Value<EP>::mkCopy(result));
119}
120
121} // anonymous namespace
122
123namespace isc {
124namespace test {
125
127 Value<ElementPtr> result = moveComments1(element);
128 return (result.get());
129}
130
132 Value<ConstElementPtr> result = moveComments1(element);
133 return (result.get());
134}
135
136}; // end of isc::test namespace
137}; // end of isc namespace
138
139namespace {
140
150template<typename EP>
151Value<EP> extractComments1(EP element) {
152 bool modified = false;
153
154 // On lists recurse on items
155 if (element->getType() == Element::list) {
156 ElementPtr result = ElementPtr(new ListElement());
157 typedef std::vector<ElementPtr> ListType;
158 const ListType& list = element->listValue();
159 for (ListType::const_iterator it = list.cbegin();
160 it != list.cend(); ++it) {
161 Value<ElementPtr> item = extractComments1(*it);
162 result->add(item.get());
163 if (!item.isShared()) {
164 modified = true;
165 }
166 }
167 if (!modified) {
168 return (Value<EP>::mkShare(element));
169 } else {
170 return (Value<EP>::mkCopy(result));
171 }
172 } else if (element->getType() != Element::map) {
173 return (Value<EP>::mkShare(element));
174 }
175
176 // Process maps: recurse on items
177 ElementPtr result = ElementPtr(new MapElement());
178 bool has_comment = false;
179 typedef std::map<std::string, ConstElementPtr> map_type;
180 const map_type& map = element->mapValue();
181 for (map_type::const_iterator it = map.cbegin(); it != map.cend(); ++it) {
182 if (it->first == "comment") {
183 // Do not traverse comment entries
184 result->set("comment", it->second);
185 } else if (it->first == "user-context") {
186 if (it->second->contains("comment")) {
187 // Note there is a entry to move
188 has_comment = true;
189 } else {
190 // Do not traverse user-context entries
191 result->set("user-context", it->second);
192 }
193 } else {
194 // Not comment or user-context
195 Value<ConstElementPtr> item = extractComments1(it->second);
196 result->set(it->first, item.get());
197 if (!item.isShared()) {
198 modified = true;
199 }
200 }
201 }
202 // Check if the value should be not modified
203 if (!has_comment && !modified) {
204 return (Value<EP>::mkShare(element));
205 }
206
207 if (has_comment) {
208 // Move the comment entry
209 const map_type& uc_map = element->get("user-context")->mapValue();
210 ElementPtr user_context = Element::createMap();
211 ConstElementPtr comment;
212 for (map_type::const_iterator it = uc_map.cbegin();
213 it != uc_map.cend(); ++it) {
214 if (it->first == "comment") {
215 comment = it->second;
216 } else {
217 user_context->set(it->first, it->second);
218 }
219 }
220 if (user_context->size() > 0) {
221 result->set("user-context", user_context);
222 }
223 result->set("comment", comment);
224 }
225
226 return (Value<EP>::mkCopy(result));
227}
228
229} // anonymous namespace
230
231namespace isc {
232namespace test {
233
235 Value<ElementPtr> result = extractComments1(element);
236 return (result.get());
237}
238
240 Value<ConstElementPtr> result = extractComments1(element);
241 return (result.get());
242}
243
244}; // end of isc::test namespace
245}; // end of isc namespace
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:268
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element.
Definition: data.cc:1096
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
ElementPtr moveComments(ElementPtr element)
Move comment entries to user-context.
ElementPtr extractComments(ElementPtr element)
Extract comment entries from user-context.
Defines the logger used by the top-level component of kea-dhcp-ddns.