blob: ef075bdccbfed08e695b9887ac99349e6f662b16 [file] [log] [blame]
Michael Gottesman0be69202015-03-05 23:28:58 +00001//===- 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
14namespace llvm {
15/// \brief An associative container with fast insertion-order (deterministic)
16/// iteration over its elements. Plus the special blot operation.
17template <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
26public:
27 typedef typename VectorTy::iterator iterator;
28 typedef typename VectorTy::const_iterator const_iterator;
29 iterator begin() { return Vector.begin(); }
30 iterator end() { return Vector.end(); }
31 const_iterator begin() const { return Vector.begin(); }
32 const_iterator end() const { return Vector.end(); }
33
Filipe Cabecinhas0da99372016-04-29 15:22:48 +000034#ifdef EXPENSIVE_CHECKS
Michael Gottesman0be69202015-03-05 23:28:58 +000035 ~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
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
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
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.
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
98 void clear() {
99 Map.clear();
100 Vector.clear();
101 }
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000102
103 bool empty() const {
104 assert(Map.empty() == Vector.empty());
105 return Map.empty();
106 }
Michael Gottesman0be69202015-03-05 23:28:58 +0000107};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000108} //