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