llvm-DenseSet.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. //===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the DenseSet and SmallDenseSet classes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. // Taken from clang-1100.247.11.10.9
  14. #ifndef LLVM_ADT_DENSESET_H
  15. #define LLVM_ADT_DENSESET_H
  16. #include "llvm-DenseMap.h"
  17. #include "llvm-DenseMapInfo.h"
  18. #include "llvm-type_traits.h"
  19. #include <algorithm>
  20. #include <cstddef>
  21. #include <initializer_list>
  22. #include <iterator>
  23. #include <utility>
  24. #include <TargetConditionals.h>
  25. #include "objc-private.h"
  26. namespace objc {
  27. namespace detail {
  28. struct DenseSetEmpty {};
  29. // Use the empty base class trick so we can create a DenseMap where the buckets
  30. // contain only a single item.
  31. template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
  32. KeyT key;
  33. public:
  34. KeyT &getFirst() { return key; }
  35. const KeyT &getFirst() const { return key; }
  36. DenseSetEmpty &getSecond() { return *this; }
  37. const DenseSetEmpty &getSecond() const { return *this; }
  38. };
  39. /// Base class for DenseSet and DenseSmallSet.
  40. ///
  41. /// MapTy should be either
  42. ///
  43. /// DenseMap<ValueT, detail::DenseSetEmpty,
  44. /// DenseMapValueInfo<detail::DenseSetEmpty>,
  45. /// ValueInfoT, detail::DenseSetPair<ValueT>>
  46. ///
  47. /// or the equivalent SmallDenseMap type. ValueInfoT must implement the
  48. /// DenseMapInfo "concept".
  49. template <typename ValueT, typename MapTy, typename ValueInfoT>
  50. class DenseSetImpl {
  51. static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
  52. "DenseMap buckets unexpectedly large!");
  53. MapTy TheMap;
  54. template <typename T>
  55. using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
  56. public:
  57. using key_type = ValueT;
  58. using value_type = ValueT;
  59. using size_type = unsigned;
  60. explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
  61. DenseSetImpl(std::initializer_list<ValueT> Elems)
  62. : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
  63. insert(Elems.begin(), Elems.end());
  64. }
  65. bool empty() const { return TheMap.empty(); }
  66. size_type size() const { return TheMap.size(); }
  67. size_t getMemorySize() const { return TheMap.getMemorySize(); }
  68. /// Grow the DenseSet so that it has at least Size buckets. Will not shrink
  69. /// the Size of the set.
  70. void resize(size_t Size) { TheMap.resize(Size); }
  71. /// Grow the DenseSet so that it can contain at least \p NumEntries items
  72. /// before resizing again.
  73. void reserve(size_t Size) { TheMap.reserve(Size); }
  74. void clear() {
  75. TheMap.clear();
  76. }
  77. /// Return 1 if the specified key is in the set, 0 otherwise.
  78. size_type count(const_arg_type_t<ValueT> V) const {
  79. return TheMap.count(V);
  80. }
  81. bool erase(const ValueT &V) {
  82. return TheMap.erase(V);
  83. }
  84. void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
  85. // Iterators.
  86. class ConstIterator;
  87. class Iterator {
  88. typename MapTy::iterator I;
  89. friend class DenseSetImpl;
  90. friend class ConstIterator;
  91. public:
  92. using difference_type = typename MapTy::iterator::difference_type;
  93. using value_type = ValueT;
  94. using pointer = value_type *;
  95. using reference = value_type &;
  96. using iterator_category = std::forward_iterator_tag;
  97. Iterator() = default;
  98. Iterator(const typename MapTy::iterator &i) : I(i) {}
  99. ValueT &operator*() { return I->getFirst(); }
  100. const ValueT &operator*() const { return I->getFirst(); }
  101. ValueT *operator->() { return &I->getFirst(); }
  102. const ValueT *operator->() const { return &I->getFirst(); }
  103. Iterator& operator++() { ++I; return *this; }
  104. Iterator operator++(int) { auto T = *this; ++I; return T; }
  105. bool operator==(const ConstIterator& X) const { return I == X.I; }
  106. bool operator!=(const ConstIterator& X) const { return I != X.I; }
  107. };
  108. class ConstIterator {
  109. typename MapTy::const_iterator I;
  110. friend class DenseSet;
  111. friend class Iterator;
  112. public:
  113. using difference_type = typename MapTy::const_iterator::difference_type;
  114. using value_type = ValueT;
  115. using pointer = const value_type *;
  116. using reference = const value_type &;
  117. using iterator_category = std::forward_iterator_tag;
  118. ConstIterator() = default;
  119. ConstIterator(const Iterator &B) : I(B.I) {}
  120. ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
  121. const ValueT &operator*() const { return I->getFirst(); }
  122. const ValueT *operator->() const { return &I->getFirst(); }
  123. ConstIterator& operator++() { ++I; return *this; }
  124. ConstIterator operator++(int) { auto T = *this; ++I; return T; }
  125. bool operator==(const ConstIterator& X) const { return I == X.I; }
  126. bool operator!=(const ConstIterator& X) const { return I != X.I; }
  127. };
  128. using iterator = Iterator;
  129. using const_iterator = ConstIterator;
  130. iterator begin() { return Iterator(TheMap.begin()); }
  131. iterator end() { return Iterator(TheMap.end()); }
  132. const_iterator begin() const { return ConstIterator(TheMap.begin()); }
  133. const_iterator end() const { return ConstIterator(TheMap.end()); }
  134. iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
  135. const_iterator find(const_arg_type_t<ValueT> V) const {
  136. return ConstIterator(TheMap.find(V));
  137. }
  138. /// Alternative version of find() which allows a different, and possibly less
  139. /// expensive, key type.
  140. /// The DenseMapInfo is responsible for supplying methods
  141. /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
  142. /// used.
  143. template <class LookupKeyT>
  144. iterator find_as(const LookupKeyT &Val) {
  145. return Iterator(TheMap.find_as(Val));
  146. }
  147. template <class LookupKeyT>
  148. const_iterator find_as(const LookupKeyT &Val) const {
  149. return ConstIterator(TheMap.find_as(Val));
  150. }
  151. void erase(Iterator I) { return TheMap.erase(I.I); }
  152. void erase(ConstIterator CI) { return TheMap.erase(CI.I); }
  153. std::pair<iterator, bool> insert(const ValueT &V) {
  154. detail::DenseSetEmpty Empty;
  155. return TheMap.try_emplace(V, Empty);
  156. }
  157. std::pair<iterator, bool> insert(ValueT &&V) {
  158. detail::DenseSetEmpty Empty;
  159. return TheMap.try_emplace(std::move(V), Empty);
  160. }
  161. /// Alternative version of insert that uses a different (and possibly less
  162. /// expensive) key type.
  163. template <typename LookupKeyT>
  164. std::pair<iterator, bool> insert_as(const ValueT &V,
  165. const LookupKeyT &LookupKey) {
  166. return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
  167. }
  168. template <typename LookupKeyT>
  169. std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
  170. return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
  171. }
  172. // Range insertion of values.
  173. template<typename InputIt>
  174. void insert(InputIt I, InputIt E) {
  175. for (; I != E; ++I)
  176. insert(*I);
  177. }
  178. };
  179. /// Equality comparison for DenseSet.
  180. ///
  181. /// Iterates over elements of LHS confirming that each element is also a member
  182. /// of RHS, and that RHS contains no additional values.
  183. /// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
  184. /// case is O(N^2) (if every hash collides).
  185. template <typename ValueT, typename MapTy, typename ValueInfoT>
  186. bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
  187. const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
  188. if (LHS.size() != RHS.size())
  189. return false;
  190. for (auto &E : LHS)
  191. if (!RHS.count(E))
  192. return false;
  193. return true;
  194. }
  195. /// Inequality comparison for DenseSet.
  196. ///
  197. /// Equivalent to !(LHS == RHS). See operator== for performance notes.
  198. template <typename ValueT, typename MapTy, typename ValueInfoT>
  199. bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
  200. const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
  201. return !(LHS == RHS);
  202. }
  203. } // end namespace detail
  204. /// Implements a dense probed hash-table based set.
  205. template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
  206. class DenseSet : public detail::DenseSetImpl<
  207. ValueT, DenseMap<ValueT, detail::DenseSetEmpty,
  208. DenseMapValueInfo<detail::DenseSetEmpty>,
  209. ValueInfoT, detail::DenseSetPair<ValueT>>,
  210. ValueInfoT> {
  211. using BaseT =
  212. detail::DenseSetImpl<ValueT,
  213. DenseMap<ValueT, detail::DenseSetEmpty,
  214. DenseMapValueInfo<detail::DenseSetEmpty>,
  215. ValueInfoT, detail::DenseSetPair<ValueT>>,
  216. ValueInfoT>;
  217. public:
  218. using BaseT::BaseT;
  219. };
  220. /// Implements a dense probed hash-table based set with some number of buckets
  221. /// stored inline.
  222. template <typename ValueT, unsigned InlineBuckets = 4,
  223. typename ValueInfoT = DenseMapInfo<ValueT>>
  224. class SmallDenseSet
  225. : public detail::DenseSetImpl<
  226. ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
  227. DenseMapValueInfo<detail::DenseSetEmpty>,
  228. ValueInfoT, detail::DenseSetPair<ValueT>>,
  229. ValueInfoT> {
  230. using BaseT = detail::DenseSetImpl<
  231. ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
  232. DenseMapValueInfo<detail::DenseSetEmpty>,
  233. ValueInfoT, detail::DenseSetPair<ValueT>>,
  234. ValueInfoT>;
  235. public:
  236. using BaseT::BaseT;
  237. };
  238. } // end namespace objc
  239. #endif // LLVM_ADT_DENSESET_H