blob: 5518b49c4095594e541857919f43819af58ec1dc [file] [log] [blame]
Eugene Zelenko57bd5a02017-10-27 01:09:08 +00001//===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===//
Michael Gottesman0be69202015-03-05 23:28:58 +00002//
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
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000010#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
11#define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
12
Michael Gottesman0be69202015-03-05 23:28:58 +000013#include "llvm/ADT/DenseMap.h"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000014#include <cassert>
15#include <cstddef>
16#include <utility>
Chandler Carruth6bda14b2017-06-06 11:49:48 +000017#include <vector>
Michael Gottesman0be69202015-03-05 23:28:58 +000018
19namespace llvm {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000020
Michael Gottesman0be69202015-03-05 23:28:58 +000021/// \brief 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.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000025 using MapTy = DenseMap<KeyT, size_t>;
Michael Gottesman0be69202015-03-05 23:28:58 +000026 MapTy Map;
27
Michael Gottesman0be69202015-03-05 23:28:58 +000028 /// Keys and values.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000029 using VectorTy = std::vector<std::pair<KeyT, ValueT>>;
Michael Gottesman0be69202015-03-05 23:28:58 +000030 VectorTy Vector;
31
32public:
Filipe Cabecinhas0da99372016-04-29 15:22:48 +000033#ifdef EXPENSIVE_CHECKS
Michael Gottesman0be69202015-03-05 23:28:58 +000034 ~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
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000048 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
Michael Gottesman0be69202015-03-05 23:28:58 +000056 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 }
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000109
110 bool empty() const {
111 assert(Map.empty() == Vector.empty());
112 return Map.empty();
113 }
Michael Gottesman0be69202015-03-05 23:28:58 +0000114};
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000115
116} // end namespace llvm
117
118#endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H