SmallSet.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- 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 SmallSet class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_SMALLSET_H
  14. #define LLVM_ADT_SMALLSET_H
  15. #include "llvm/ADT/None.h"
  16. #include "llvm/ADT/SmallPtrSet.h"
  17. #include "llvm/ADT/SmallVector.h"
  18. #include <set>
  19. namespace llvm {
  20. /// SmallSet - This maintains a set of unique values, optimizing for the case
  21. /// when the set is small (less than N). In this case, the set can be
  22. /// maintained with no mallocs. If the set gets large, we expand to using an
  23. /// std::set to maintain reasonable lookup times.
  24. ///
  25. /// Note that this set does not provide a way to iterate over members in the
  26. /// set.
  27. template <typename T, unsigned N, typename C = std::less<T> >
  28. class SmallSet {
  29. /// Use a SmallVector to hold the elements here (even though it will never
  30. /// reach its 'large' stage) to avoid calling the default ctors of elements
  31. /// we will never use.
  32. SmallVector<T, N> Vector;
  33. std::set<T, C> Set;
  34. typedef typename SmallVector<T, N>::const_iterator VIterator;
  35. typedef typename SmallVector<T, N>::iterator mutable_iterator;
  36. public:
  37. typedef size_t size_type;
  38. SmallSet() {}
  39. bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
  40. return Vector.empty() && Set.empty();
  41. }
  42. size_type size() const {
  43. return isSmall() ? Vector.size() : Set.size();
  44. }
  45. /// count - Return 1 if the element is in the set, 0 otherwise.
  46. size_type count(const T &V) const {
  47. if (isSmall()) {
  48. // Since the collection is small, just do a linear search.
  49. return vfind(V) == Vector.end() ? 0 : 1;
  50. } else {
  51. return Set.count(V);
  52. }
  53. }
  54. /// insert - Insert an element into the set if it isn't already there.
  55. /// Returns true if the element is inserted (it was not in the set before).
  56. /// The first value of the returned pair is unused and provided for
  57. /// partial compatibility with the standard library self-associative container
  58. /// concept.
  59. // FIXME: Add iterators that abstract over the small and large form, and then
  60. // return those here.
  61. std::pair<NoneType, bool> insert(const T &V) {
  62. if (!isSmall())
  63. return std::make_pair(None, Set.insert(V).second);
  64. VIterator I = vfind(V);
  65. if (I != Vector.end()) // Don't reinsert if it already exists.
  66. return std::make_pair(None, false);
  67. if (Vector.size() < N) {
  68. Vector.push_back(V);
  69. return std::make_pair(None, true);
  70. }
  71. // Otherwise, grow from vector to set.
  72. while (!Vector.empty()) {
  73. Set.insert(Vector.back());
  74. Vector.pop_back();
  75. }
  76. Set.insert(V);
  77. return std::make_pair(None, true);
  78. }
  79. template <typename IterT>
  80. void insert(IterT I, IterT E) {
  81. for (; I != E; ++I)
  82. insert(*I);
  83. }
  84. bool erase(const T &V) {
  85. if (!isSmall())
  86. return Set.erase(V);
  87. for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
  88. if (*I == V) {
  89. Vector.erase(I);
  90. return true;
  91. }
  92. return false;
  93. }
  94. void clear() {
  95. Vector.clear();
  96. Set.clear();
  97. }
  98. private:
  99. bool isSmall() const { return Set.empty(); }
  100. VIterator vfind(const T &V) const {
  101. for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
  102. if (*I == V)
  103. return I;
  104. return Vector.end();
  105. }
  106. };
  107. /// If this set is of pointer values, transparently switch over to using
  108. /// SmallPtrSet for performance.
  109. template <typename PointeeType, unsigned N>
  110. class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {};
  111. } // end namespace llvm
  112. #endif