BlotMapVector.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
  9. #define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
  10. #include "llvm/ADT/DenseMap.h"
  11. #include <cassert>
  12. #include <cstddef>
  13. #include <utility>
  14. #include <vector>
  15. namespace llvm {
  16. /// An associative container with fast insertion-order (deterministic)
  17. /// iteration over its elements. Plus the special blot operation.
  18. template <class KeyT, class ValueT> class BlotMapVector {
  19. /// Map keys to indices in Vector.
  20. using MapTy = DenseMap<KeyT, size_t>;
  21. MapTy Map;
  22. /// Keys and values.
  23. using VectorTy = std::vector<std::pair<KeyT, ValueT>>;
  24. VectorTy Vector;
  25. public:
  26. #ifdef EXPENSIVE_CHECKS
  27. ~BlotMapVector() {
  28. assert(Vector.size() >= Map.size()); // May differ due to blotting.
  29. for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E;
  30. ++I) {
  31. assert(I->second < Vector.size());
  32. assert(Vector[I->second].first == I->first);
  33. }
  34. for (typename VectorTy::const_iterator I = Vector.begin(), E = Vector.end();
  35. I != E; ++I)
  36. assert(!I->first || (Map.count(I->first) &&
  37. Map[I->first] == size_t(I - Vector.begin())));
  38. }
  39. #endif
  40. using iterator = typename VectorTy::iterator;
  41. using const_iterator = typename VectorTy::const_iterator;
  42. iterator begin() { return Vector.begin(); }
  43. iterator end() { return Vector.end(); }
  44. const_iterator begin() const { return Vector.begin(); }
  45. const_iterator end() const { return Vector.end(); }
  46. ValueT &operator[](const KeyT &Arg) {
  47. std::pair<typename MapTy::iterator, bool> Pair =
  48. Map.insert(std::make_pair(Arg, size_t(0)));
  49. if (Pair.second) {
  50. size_t Num = Vector.size();
  51. Pair.first->second = Num;
  52. Vector.push_back(std::make_pair(Arg, ValueT()));
  53. return Vector[Num].second;
  54. }
  55. return Vector[Pair.first->second].second;
  56. }
  57. std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &InsertPair) {
  58. std::pair<typename MapTy::iterator, bool> Pair =
  59. Map.insert(std::make_pair(InsertPair.first, size_t(0)));
  60. if (Pair.second) {
  61. size_t Num = Vector.size();
  62. Pair.first->second = Num;
  63. Vector.push_back(InsertPair);
  64. return std::make_pair(Vector.begin() + Num, true);
  65. }
  66. return std::make_pair(Vector.begin() + Pair.first->second, false);
  67. }
  68. iterator find(const KeyT &Key) {
  69. typename MapTy::iterator It = Map.find(Key);
  70. if (It == Map.end())
  71. return Vector.end();
  72. return Vector.begin() + It->second;
  73. }
  74. const_iterator find(const KeyT &Key) const {
  75. typename MapTy::const_iterator It = Map.find(Key);
  76. if (It == Map.end())
  77. return Vector.end();
  78. return Vector.begin() + It->second;
  79. }
  80. /// This is similar to erase, but instead of removing the element from the
  81. /// vector, it just zeros out the key in the vector. This leaves iterators
  82. /// intact, but clients must be prepared for zeroed-out keys when iterating.
  83. void blot(const KeyT &Key) {
  84. typename MapTy::iterator It = Map.find(Key);
  85. if (It == Map.end())
  86. return;
  87. Vector[It->second].first = KeyT();
  88. Map.erase(It);
  89. }
  90. void clear() {
  91. Map.clear();
  92. Vector.clear();
  93. }
  94. bool empty() const {
  95. assert(Map.empty() == Vector.empty());
  96. return Map.empty();
  97. }
  98. };
  99. } // end namespace llvm
  100. #endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H