| //===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H | |
| #define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H | |
| #include "llvm/ADT/DenseMap.h" | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <utility> | |
| #include <vector> | |
| namespace llvm { | |
| /// An associative container with fast insertion-order (deterministic) | |
| /// iteration over its elements. Plus the special blot operation. | |
| template <class KeyT, class ValueT> class BlotMapVector { | |
| /// Map keys to indices in Vector. | |
| using MapTy = DenseMap<KeyT, size_t>; | |
| MapTy Map; | |
| /// Keys and values. | |
| using VectorTy = std::vector<std::pair<KeyT, ValueT>>; | |
| VectorTy Vector; | |
| public: | |
| #ifdef EXPENSIVE_CHECKS | |
| ~BlotMapVector() { | |
| assert(Vector.size() >= Map.size()); // May differ due to blotting. | |
| for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E; | |
| ++I) { | |
| assert(I->second < Vector.size()); | |
| assert(Vector[I->second].first == I->first); | |
| } | |
| for (typename VectorTy::const_iterator I = Vector.begin(), E = Vector.end(); | |
| I != E; ++I) | |
| assert(!I->first || (Map.count(I->first) && | |
| Map[I->first] == size_t(I - Vector.begin()))); | |
| } | |
| #endif | |
| using iterator = typename VectorTy::iterator; | |
| using const_iterator = typename VectorTy::const_iterator; | |
| iterator begin() { return Vector.begin(); } | |
| iterator end() { return Vector.end(); } | |
| const_iterator begin() const { return Vector.begin(); } | |
| const_iterator end() const { return Vector.end(); } | |
| ValueT &operator[](const KeyT &Arg) { | |
| std::pair<typename MapTy::iterator, bool> Pair = | |
| Map.insert(std::make_pair(Arg, size_t(0))); | |
| if (Pair.second) { | |
| size_t Num = Vector.size(); | |
| Pair.first->second = Num; | |
| Vector.push_back(std::make_pair(Arg, ValueT())); | |
| return Vector[Num].second; | |
| } | |
| return Vector[Pair.first->second].second; | |
| } | |
| std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &InsertPair) { | |
| std::pair<typename MapTy::iterator, bool> Pair = | |
| Map.insert(std::make_pair(InsertPair.first, size_t(0))); | |
| if (Pair.second) { | |
| size_t Num = Vector.size(); | |
| Pair.first->second = Num; | |
| Vector.push_back(InsertPair); | |
| return std::make_pair(Vector.begin() + Num, true); | |
| } | |
| return std::make_pair(Vector.begin() + Pair.first->second, false); | |
| } | |
| iterator find(const KeyT &Key) { | |
| typename MapTy::iterator It = Map.find(Key); | |
| if (It == Map.end()) | |
| return Vector.end(); | |
| return Vector.begin() + It->second; | |
| } | |
| const_iterator find(const KeyT &Key) const { | |
| typename MapTy::const_iterator It = Map.find(Key); | |
| if (It == Map.end()) | |
| return Vector.end(); | |
| return Vector.begin() + It->second; | |
| } | |
| /// This is similar to erase, but instead of removing the element from the | |
| /// vector, it just zeros out the key in the vector. This leaves iterators | |
| /// intact, but clients must be prepared for zeroed-out keys when iterating. | |
| void blot(const KeyT &Key) { | |
| typename MapTy::iterator It = Map.find(Key); | |
| if (It == Map.end()) | |
| return; | |
| Vector[It->second].first = KeyT(); | |
| Map.erase(It); | |
| } | |
| void clear() { | |
| Map.clear(); | |
| Vector.clear(); | |
| } | |
| bool empty() const { | |
| assert(Map.empty() == Vector.empty()); | |
| return Map.empty(); | |
| } | |
| }; | |
| } // end namespace llvm | |
| #endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H |