Commit 499f6ca7 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5351] Added combine (merge variant) in libcc

parent 49288c88
......@@ -1068,6 +1068,48 @@ merge(ElementPtr element, ConstElementPtr other) {
}
}
void
combine(ElementPtr element, ConstElementPtr other) {
if (element->getType() != Element::map ||
other->getType() != Element::map) {
isc_throw(TypeError, "combine arguments not MapElements");
}
const std::map<std::string, ConstElementPtr>& m = other->mapValue();
for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
it != m.end() ; ++it) {
if (isNull(it->second)) {
isc_throw(BadValue, "combine got a null pointer");
}
if (!element->contains(it->first)) {
element->set(it->first, it->second);
continue;
}
ConstElementPtr e = element->get(it->first);
if (isNull(e)) {
isc_throw(BadValue, "combine got a null pointer");
}
ElementPtr le = Element::createList();
size_t i;
if (e->getType() == Element::list) {
le = Element::createList(e->getPosition());
for (i = 0; i < e->size(); ++i) {
le->add(e->getNonConst(i));
}
} else {
le->add(boost::const_pointer_cast<Element>(e));
}
if (it->second->getType() == Element::list) {
for (i = 0; i < it->second->size(); ++i) {
le->add(it->second->getNonConst(i));
}
} else {
le->add(boost::const_pointer_cast<Element>(it->second));
}
element->set(it->first, le);
}
}
ElementPtr
copy(ConstElementPtr from, int level) {
if (isNull(from)) {
......
......@@ -732,6 +732,23 @@ ConstElementPtr removeIdentical(ConstElementPtr a, ConstElementPtr b);
/// Raises a TypeError if either ElementPtr is not a MapElement
void merge(ElementPtr element, ConstElementPtr other);
/// @brief Combines the data from other into element.
/// (on the first level). Both elements must be
/// MapElements.
/// Every string,value pair in other is copied into element
/// (the ElementPtr of value is copied, this is not a new object)
/// When there is already a value for a key in element if both are lists
/// the other list is appended to the element list, if only one is a
/// list the not list value is added to the list. If none is a list
/// a list is created, the element value is added and the other value
/// is added.
///
/// @param element target map
/// @param other the map to combine with element
/// @throw raises a TypeError if either ElementPtr is not a MapElement
/// @throw raises a BadValue is a null pointer occurs.
void combine(ElementPtr element, ConstElementPtr other);
/// @brief Copy the data up to a nesting level.
///
/// The copy is a deep copy so nothing is shared if it is not
......
......@@ -985,6 +985,89 @@ TEST(Element, merge) {
}
// This test checks combine.
TEST(Element, combine) {
ElementPtr a = Element::createMap();
ElementPtr b = Element::createMap();
ConstElementPtr c = Element::createMap();
combine(a, b);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("1");
b = Element::createMap();
EXPECT_THROW(combine(a, b), TypeError);
a = Element::createMap();
b = Element::fromJSON("{ \"a\": 1 }");
c = Element::fromJSON("{ \"a\": 1 }");
combine(a, b);
EXPECT_EQ(*a, *c);
a = Element::createMap();
b = Element::fromJSON("{ \"a\": 1 }");
c = Element::fromJSON("{ \"a\": 1 }");
combine(b, a);
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": 1 }");
b = Element::fromJSON("{ \"a\": 2 }");
c = Element::fromJSON("{ \"a\": [ 1, 2 ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": 1 }");
b = Element::fromJSON("{ \"a\": 2 }");
c = Element::fromJSON("{ \"a\": [ 2, 1 ] }");
combine(b, a);
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
c = Element::fromJSON("{ \"a\": [ { \"b\": \"c\" } ,{ \"b\": \"d\" } ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
c = Element::fromJSON("{ \"a\": [ { \"b\": \"d\" }, { \"b\": \"c\" } ] }");
combine(b, a);
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": 1, \"b\": 2 }");
b = Element::fromJSON("{ \"a\": 2, \"b\": 1 }");
c = Element::fromJSON("{ \"a\": [ 1, 2 ], \"b\": [ 2, 1 ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": [] }");
b = Element::fromJSON("{ \"a\": 1 }");
c = Element::fromJSON("{ \"a\": [ 1 ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
combine(b, a);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": [] }");
b = Element::fromJSON("{ \"a\": [ 1 ] }");
c = Element::fromJSON("{ \"a\": [ 1 ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
combine(b, a);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": [ 1 ] }");
b = Element::fromJSON("{ \"a\": [ 2 ] }");
c = Element::fromJSON("{ \"a\": [ 1, 2 ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": [ 1, 2, 3 ] }");
b = Element::fromJSON("{ \"a\": [ 2, 3, 4 ] }");
c = Element::fromJSON("{ \"a\": [ 1, 2, 3, 2, 3, 4 ] }");
combine(a, b);
EXPECT_EQ(*a, *c);
}
// This test checks copy.
TEST(Element, copy) {
// Null pointer
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment