Skip to content

Commit

Permalink
Merge pull request grpc#20044 from markdroth/map_copy
Browse files Browse the repository at this point in the history
Make Map<> copyable.
  • Loading branch information
markdroth authored Aug 23, 2019
2 parents e25e7c9 + 5d646ff commit aa0661c
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
71 changes: 71 additions & 0 deletions src/core/lib/gprpp/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class Map {
typedef Pair<key_type, mapped_type> value_type;
typedef Compare key_compare;
class iterator;
class const_iterator;

Map() = default;
~Map() { clear(); }
Expand All @@ -83,6 +84,22 @@ class Map {
return *this;
}

// Copyable.
Map(const Map& other) {
for (const auto& p : other) {
emplace(p);
}
}
Map& operator=(const Map& other) {
if (this != &other) {
clear();
for (const auto& p : other) {
emplace(p);
}
}
return *this;
}

T& operator[](key_type&& key);
T& operator[](const key_type& key);
iterator find(const key_type& k);
Expand Down Expand Up @@ -117,6 +134,13 @@ class Map {

iterator end() { return iterator(this, nullptr); }

const_iterator begin() const {
Entry* curr = GetMinEntry(root_);
return const_iterator(this, curr);
}

const_iterator end() const { return const_iterator(this, nullptr); }

iterator lower_bound(const Key& k) {
// This is a workaround for "const key_compare compare;"
// because some versions of compilers cannot build this by requiring
Expand Down Expand Up @@ -209,6 +233,53 @@ class Map<Key, T, Compare>::iterator
GrpcMap* map_;
};

template <class Key, class T, class Compare>
class Map<Key, T, Compare>::const_iterator
: public std::iterator<std::input_iterator_tag, Pair<Key, T>, int32_t,
Pair<Key, T>*, Pair<Key, T>&> {
public:
const_iterator(const const_iterator& iter)
: curr_(iter.curr_), map_(iter.map_) {}
bool operator==(const const_iterator& rhs) const {
return (curr_ == rhs.curr_);
}
bool operator!=(const const_iterator& rhs) const {
return (curr_ != rhs.curr_);
}

const_iterator& operator++() {
curr_ = map_->InOrderSuccessor(curr_);
return *this;
}

const_iterator operator++(int) {
Entry* prev = curr_;
curr_ = map_->InOrderSuccessor(curr_);
return const_iterator(map_, prev);
}

const_iterator& operator=(const const_iterator& other) {
if (this != &other) {
this->curr_ = other.curr_;
this->map_ = other.map_;
}
return *this;
}

// operator*()
const value_type& operator*() const { return curr_->pair; }

// operator->()
const value_type* operator->() const { return &curr_->pair; }

private:
friend class Map<key_type, mapped_type, key_compare>;
using GrpcMap = typename ::grpc_core::Map<Key, T, Compare>;
const_iterator(const GrpcMap* map, Entry* curr) : curr_(curr), map_(map) {}
Entry* curr_;
const GrpcMap* map_;
};

template <class Key, class T, class Compare>
T& Map<Key, T, Compare>::operator[](key_type&& key) {
auto iter = find(key);
Expand Down
29 changes: 29 additions & 0 deletions test/core/gprpp/map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,35 @@ TEST_F(MapTest, MoveAssignment) {
EXPECT_EQ(test_map2.end(), test_map2.find("xxx"));
}

// Test copy ctor
TEST_F(MapTest, CopyCtor) {
Map<const char*, Payload, StringLess> test_map;
for (int i = 0; i < 5; i++) {
test_map.emplace(kKeys[i], Payload(i));
}
Map<const char*, Payload, StringLess> test_map2 = test_map;
for (int i = 0; i < 5; i++) {
EXPECT_EQ(i, test_map.find(kKeys[i])->second.data());
EXPECT_EQ(i, test_map2.find(kKeys[i])->second.data());
}
}

// Test copy assignment
TEST_F(MapTest, CopyAssignment) {
Map<const char*, Payload, StringLess> test_map;
for (int i = 0; i < 5; i++) {
test_map.emplace(kKeys[i], Payload(i));
}
Map<const char*, Payload, StringLess> test_map2;
test_map2.emplace("xxx", Payload(123));
test_map2 = test_map;
for (int i = 0; i < 5; i++) {
EXPECT_EQ(i, test_map.find(kKeys[i])->second.data());
EXPECT_EQ(i, test_map2.find(kKeys[i])->second.data());
}
EXPECT_EQ(test_map2.end(), test_map2.find("xxx"));
}

} // namespace testing
} // namespace grpc_core

Expand Down

0 comments on commit aa0661c

Please sign in to comment.