map_difference: Simplify difference value

Simplify the return value of map_difference() to return set of keys.
This makes it possible to use the function with value types such as
foreign_ptr<> that are non-copyable.

Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
This commit is contained in:
Pekka Enberg
2015-06-02 14:02:31 +03:00
committed by Avi Kivity
parent 7e98e39afd
commit 5418e32fc7
3 changed files with 45 additions and 40 deletions

View File

@@ -556,23 +556,24 @@ std::vector<const char*> ALL { KEYSPACES, COLUMNFAMILIES, COLUMNS, TRIGGERS, USE
return *x == *y;
});
for (auto&& entry : diff.entries_only_on_right) {
if (!entry.second->empty()) {
created.emplace_back(std::move(entry));
for (auto&& key : diff.entries_only_on_right) {
auto&& value = before[key];
if (!value->empty()) {
created.emplace_back(std::make_pair(key, std::move(value)));
}
}
for (auto&& entry : diff.entries_differing) {
sstring keyspace_name = entry.first;
for (auto&& key : diff.entries_differing) {
sstring keyspace_name = key;
auto&& pre = entry.second.left_value;
auto&& post = entry.second.right_value;
auto&& pre = before[key];
auto&& post = after[key];
if (!pre->empty() && !post->empty()) {
altered.emplace_back(keyspace_name);
} else if (!pre->empty()) {
dropped.emplace(keyspace_name);
} else if (!post->empty()) { // a (re)created keyspace
created.emplace_back(entry.first, std::move(post));
created.emplace_back(std::make_pair(key, std::move(post)));
}
}
return do_with(std::move(created), [&proxy, altered = std::move(altered)] (auto& created) {

View File

@@ -5,37 +5,27 @@
#pragma once
#include <map>
#include <set>
template<typename Tp>
struct value_difference {
Tp left_value;
Tp right_value;
value_difference(const Tp& left_value_, const Tp& right_value_)
: left_value(left_value_)
, right_value(right_value_)
{ }
};
template<typename Key, typename Tp, typename Compare, typename Alloc>
template<typename Key>
struct map_difference {
// Entries in left map whose keys don't exist in the right map.
std::map<Key, Tp, Compare> entries_only_on_left;
std::set<Key> entries_only_on_left;
// Entries in right map whose keys don't exist in the left map.
std::map<Key, Tp, Compare> entries_only_on_right;
std::set<Key> entries_only_on_right;
// Entries that appear in both maps with the same value.
std::map<Key, Tp, Compare> entries_in_common;
std::set<Key> entries_in_common;
// Entries that appear in both maps but have different values.
std::map<Key, value_difference<Tp>, Compare> entries_differing;
std::set<Key> entries_differing;
map_difference(const Compare& cmp, const Alloc& alloc)
: entries_only_on_left{cmp, alloc}
, entries_only_on_right{cmp, alloc}
, entries_in_common{cmp, alloc}
, entries_differing{cmp, alloc}
map_difference()
: entries_only_on_left{}
, entries_only_on_right{}
, entries_in_common{}
, entries_differing{}
{ }
};
@@ -45,15 +35,17 @@ template<typename Key,
typename Eq = std::equal_to<Tp>,
typename Alloc>
inline
map_difference<Key, Tp, Compare, Alloc>
map_difference<Key>
difference(const std::map<Key, Tp, Compare, Alloc>& left,
const std::map<Key, Tp, Compare, Alloc>& right,
Compare key_comp,
Eq equals = Eq(),
Alloc alloc = Alloc())
{
map_difference<Key, Tp, Compare, Alloc> diff{key_comp, alloc};
diff.entries_only_on_right = right;
map_difference<Key> diff{};
for (auto&& kv : right) {
diff.entries_only_on_right.emplace(kv.first);
}
for (auto&& kv : left) {
auto&& left_key = kv.first;
auto&& it = right.find(left_key);
@@ -62,13 +54,12 @@ difference(const std::map<Key, Tp, Compare, Alloc>& left,
const Tp& left_value = kv.second;
const Tp& right_value = it->second;
if (equals(left_value, right_value)) {
diff.entries_in_common.emplace(kv);
diff.entries_in_common.emplace(left_key);
} else {
value_difference<Tp> value_diff{left_value, right_value};
diff.entries_differing.emplace(left_key, std::move(value_diff));
diff.entries_differing.emplace(left_key);
}
} else {
diff.entries_only_on_left.emplace(kv);
diff.entries_only_on_left.emplace(left_key);
}
}
return diff;
@@ -76,7 +67,7 @@ difference(const std::map<Key, Tp, Compare, Alloc>& left,
template<typename Key, typename Tp, typename Compare, typename Eq, typename Alloc>
inline
map_difference<Key, Tp, Compare, Alloc>
map_difference<Key>
difference(const std::map<Key, Tp, Compare, Alloc>& left, const std::map<Key, Tp, Compare, Alloc>& right, Eq equals) {
return difference(left, right, left.key_comp(), equals);
}

View File

@@ -10,6 +10,7 @@
#include "map_difference.hh"
#include <map>
#include <set>
using namespace std;
@@ -34,12 +35,16 @@ BOOST_AUTO_TEST_CASE(left_empty) {
right.emplace(1, 100);
right.emplace(2, 200);
set<int> keys;
keys.emplace(1);
keys.emplace(2);
auto diff = difference(left, right, [](int x, int y) -> bool {
return x == y;
});
BOOST_REQUIRE(diff.entries_only_on_left.empty());
BOOST_REQUIRE(diff.entries_only_on_right == right);
BOOST_REQUIRE(diff.entries_only_on_right == keys);
BOOST_REQUIRE(diff.entries_in_common.empty());
BOOST_REQUIRE(diff.entries_differing.empty());
}
@@ -51,11 +56,15 @@ BOOST_AUTO_TEST_CASE(right_empty) {
left.emplace(1, 100);
left.emplace(2, 200);
set<int> keys;
keys.emplace(1);
keys.emplace(2);
auto diff = difference(left, right, [](int x, int y) -> bool {
return x == y;
});
BOOST_REQUIRE(diff.entries_only_on_left == left);
BOOST_REQUIRE(diff.entries_only_on_left == keys);
BOOST_REQUIRE(diff.entries_only_on_right.empty());
BOOST_REQUIRE(diff.entries_in_common.empty());
BOOST_REQUIRE(diff.entries_differing.empty());
@@ -71,13 +80,17 @@ BOOST_AUTO_TEST_CASE(both_same) {
right.emplace(1, 100);
right.emplace(2, 200);
set<int> keys;
keys.emplace(1);
keys.emplace(2);
auto diff = difference(left, right, [](int x, int y) -> bool {
return x == y;
});
BOOST_REQUIRE(diff.entries_only_on_left.empty());
BOOST_REQUIRE(diff.entries_only_on_right.empty());
BOOST_REQUIRE(diff.entries_in_common == left);
BOOST_REQUIRE(diff.entries_in_common == keys);
BOOST_REQUIRE(diff.entries_differing.empty());
}