StringKeyedMap.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Copyright 2015-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. // Copyright 2013-present Facebook. All Rights Reserved.
  17. // @author: Pavlo Kushnir (pavlo)
  18. #pragma once
  19. #include <initializer_list>
  20. #include <map>
  21. #include <memory>
  22. #include <folly/Range.h>
  23. #include <folly/experimental/StringKeyedCommon.h>
  24. namespace folly {
  25. /**
  26. * Wrapper class for map<string, Value> that can
  27. * perform lookup operations with StringPiece, not only string.
  28. *
  29. * It uses kind of hack: string pointed by StringPiece is copied when
  30. * StringPiece is inserted into map
  31. */
  32. template <
  33. class Value,
  34. class Compare = std::less<StringPiece>,
  35. class Alloc = std::allocator<std::pair<const StringPiece, Value>>>
  36. class StringKeyedMap : private std::map<StringPiece, Value, Compare, Alloc> {
  37. private:
  38. using Base = std::map<StringPiece, Value, Compare, Alloc>;
  39. public:
  40. typedef typename Base::key_type key_type;
  41. typedef typename Base::mapped_type mapped_type;
  42. typedef typename Base::value_type value_type;
  43. typedef typename Base::key_compare key_compare;
  44. typedef typename Base::allocator_type allocator_type;
  45. typedef typename Base::reference reference;
  46. typedef typename Base::const_reference const_reference;
  47. typedef typename Base::pointer pointer;
  48. typedef typename Base::const_pointer const_pointer;
  49. typedef typename Base::iterator iterator;
  50. typedef typename Base::const_iterator const_iterator;
  51. typedef typename Base::reverse_iterator reverse_iterator;
  52. typedef typename Base::const_reverse_iterator const_reverse_iterator;
  53. typedef typename Base::difference_type difference_type;
  54. typedef typename Base::size_type size_type;
  55. using Base::get_allocator;
  56. // Ctors in the same order as
  57. // http://cplusplus.com/reference/map/map/map/
  58. explicit StringKeyedMap(
  59. const key_compare& comp = key_compare(),
  60. const allocator_type& alloc = allocator_type())
  61. : Base(comp, alloc) {}
  62. explicit StringKeyedMap(const allocator_type& alloc) : Base(alloc) {}
  63. template <class InputIterator>
  64. explicit StringKeyedMap(
  65. InputIterator b,
  66. InputIterator e,
  67. const key_compare& comp = key_compare(),
  68. const allocator_type& alloc = allocator_type())
  69. : Base(comp, alloc) {
  70. for (; b != e; ++b) {
  71. // emplace() will carry the duplication
  72. emplace(b->first, b->second);
  73. }
  74. }
  75. StringKeyedMap(const StringKeyedMap& rhs)
  76. : StringKeyedMap(rhs, rhs.get_allocator()) {}
  77. StringKeyedMap(const StringKeyedMap& rhs, const allocator_type& a)
  78. : StringKeyedMap(rhs.begin(), rhs.end(), rhs.key_comp(), a) {}
  79. StringKeyedMap(StringKeyedMap&& other) noexcept : Base(std::move(other)) {}
  80. StringKeyedMap(StringKeyedMap&& other, const allocator_type& /* a */) noexcept
  81. : Base(std::move(other) /*, a*/ /* not supported by gcc */) {}
  82. StringKeyedMap(
  83. std::initializer_list<value_type> il,
  84. const key_compare& comp = key_compare(),
  85. const allocator_type& alloc = allocator_type())
  86. : StringKeyedMap(il.begin(), il.end(), comp, alloc) {}
  87. StringKeyedMap& operator=(const StringKeyedMap& other) & {
  88. if (this == &other) {
  89. return *this;
  90. }
  91. return *this = StringKeyedMap(other);
  92. }
  93. StringKeyedMap& operator=(StringKeyedMap&& other) & noexcept {
  94. assert(this != &other);
  95. clear();
  96. Base::operator=(std::move(other));
  97. return *this;
  98. }
  99. using Base::begin;
  100. using Base::cbegin;
  101. using Base::cend;
  102. using Base::crbegin;
  103. using Base::crend;
  104. using Base::empty;
  105. using Base::end;
  106. using Base::max_size;
  107. using Base::rbegin;
  108. using Base::rend;
  109. using Base::size;
  110. bool operator==(StringKeyedMap const& other) const {
  111. Base const& lhs = *this;
  112. Base const& rhs = static_cast<Base const&>(other);
  113. return lhs == rhs;
  114. }
  115. // no need for copy/move overload as StringPiece is small struct
  116. mapped_type& operator[](StringPiece key) {
  117. auto it = find(key);
  118. if (it != end()) {
  119. return it->second;
  120. }
  121. // operator[] will create new (key, value) pair
  122. // we need to allocate memory for key
  123. return Base::operator[](stringPieceDup(key, get_allocator()));
  124. }
  125. using Base::at;
  126. using Base::count;
  127. using Base::find;
  128. using Base::lower_bound;
  129. using Base::upper_bound;
  130. template <class... Args>
  131. std::pair<iterator, bool> emplace(StringPiece key, Args&&... args) {
  132. auto it = find(key);
  133. if (it != end()) {
  134. return {it, false};
  135. }
  136. return Base::emplace(
  137. stringPieceDup(key, get_allocator()), std::forward<Args>(args)...);
  138. }
  139. std::pair<iterator, bool> insert(value_type val) {
  140. auto it = find(val.first);
  141. if (it != end()) {
  142. return {it, false};
  143. }
  144. return Base::insert(std::make_pair(
  145. stringPieceDup(val.first, get_allocator()), std::move(val.second)));
  146. }
  147. iterator erase(const_iterator position) {
  148. auto key = position->first;
  149. auto result = Base::erase(position);
  150. stringPieceDel(key, get_allocator());
  151. return result;
  152. }
  153. size_type erase(StringPiece key) {
  154. auto it = find(key);
  155. if (it == end()) {
  156. return 0;
  157. }
  158. erase(it);
  159. return 1;
  160. }
  161. void clear() noexcept {
  162. for (auto& it : *this) {
  163. stringPieceDel(it.first, get_allocator());
  164. }
  165. Base::clear();
  166. }
  167. using Base::swap;
  168. ~StringKeyedMap() {
  169. // Here we assume that map doesn't use keys in destructor
  170. for (auto& it : *this) {
  171. stringPieceDel(it.first, get_allocator());
  172. }
  173. }
  174. };
  175. } // namespace folly