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