Home | History | Annotate | Download | only in ADT
      1 //===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- 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 // This file implements a map that provides insertion order iteration. The
     11 // interface is purposefully minimal. The key is assumed to be cheap to copy
     12 // and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
     13 // a std::vector.
     14 //
     15 //===----------------------------------------------------------------------===//
     16 
     17 #ifndef LLVM_ADT_MAPVECTOR_H
     18 #define LLVM_ADT_MAPVECTOR_H
     19 
     20 #include "llvm/ADT/DenseMap.h"
     21 #include "llvm/ADT/SmallVector.h"
     22 #include <algorithm>
     23 #include <cassert>
     24 #include <cstddef>
     25 #include <iterator>
     26 #include <type_traits>
     27 #include <utility>
     28 #include <vector>
     29 
     30 namespace llvm {
     31 
     32 /// This class implements a map that also provides access to all stored values
     33 /// in a deterministic order. The values are kept in a std::vector and the
     34 /// mapping is done with DenseMap from Keys to indexes in that vector.
     35 template<typename KeyT, typename ValueT,
     36          typename MapType = DenseMap<KeyT, unsigned>,
     37          typename VectorType = std::vector<std::pair<KeyT, ValueT>>>
     38 class MapVector {
     39   using value_type = typename VectorType::value_type;
     40   using size_type = typename VectorType::size_type;
     41 
     42   MapType Map;
     43   VectorType Vector;
     44 
     45 public:
     46   using iterator = typename VectorType::iterator;
     47   using const_iterator = typename VectorType::const_iterator;
     48   using reverse_iterator = typename VectorType::reverse_iterator;
     49   using const_reverse_iterator = typename VectorType::const_reverse_iterator;
     50 
     51   /// Clear the MapVector and return the underlying vector.
     52   VectorType takeVector() {
     53     Map.clear();
     54     return std::move(Vector);
     55   }
     56 
     57   size_type size() const { return Vector.size(); }
     58 
     59   iterator begin() { return Vector.begin(); }
     60   const_iterator begin() const { return Vector.begin(); }
     61   iterator end() { return Vector.end(); }
     62   const_iterator end() const { return Vector.end(); }
     63 
     64   reverse_iterator rbegin() { return Vector.rbegin(); }
     65   const_reverse_iterator rbegin() const { return Vector.rbegin(); }
     66   reverse_iterator rend() { return Vector.rend(); }
     67   const_reverse_iterator rend() const { return Vector.rend(); }
     68 
     69   bool empty() const {
     70     return Vector.empty();
     71   }
     72 
     73   std::pair<KeyT, ValueT>       &front()       { return Vector.front(); }
     74   const std::pair<KeyT, ValueT> &front() const { return Vector.front(); }
     75   std::pair<KeyT, ValueT>       &back()        { return Vector.back(); }
     76   const std::pair<KeyT, ValueT> &back()  const { return Vector.back(); }
     77 
     78   void clear() {
     79     Map.clear();
     80     Vector.clear();
     81   }
     82 
     83   void swap(MapVector &RHS) {
     84     std::swap(Map, RHS.Map);
     85     std::swap(Vector, RHS.Vector);
     86   }
     87 
     88   ValueT &operator[](const KeyT &Key) {
     89     std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
     90     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
     91     unsigned &I = Result.first->second;
     92     if (Result.second) {
     93       Vector.push_back(std::make_pair(Key, ValueT()));
     94       I = Vector.size() - 1;
     95     }
     96     return Vector[I].second;
     97   }
     98 
     99   // Returns a copy of the value.  Only allowed if ValueT is copyable.
    100   ValueT lookup(const KeyT &Key) const {
    101     static_assert(std::is_copy_constructible<ValueT>::value,
    102                   "Cannot call lookup() if ValueT is not copyable.");
    103     typename MapType::const_iterator Pos = Map.find(Key);
    104     return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
    105   }
    106 
    107   std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
    108     std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
    109     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
    110     unsigned &I = Result.first->second;
    111     if (Result.second) {
    112       Vector.push_back(std::make_pair(KV.first, KV.second));
    113       I = Vector.size() - 1;
    114       return std::make_pair(std::prev(end()), true);
    115     }
    116     return std::make_pair(begin() + I, false);
    117   }
    118 
    119   std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
    120     // Copy KV.first into the map, then move it into the vector.
    121     std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
    122     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
    123     unsigned &I = Result.first->second;
    124     if (Result.second) {
    125       Vector.push_back(std::move(KV));
    126       I = Vector.size() - 1;
    127       return std::make_pair(std::prev(end()), true);
    128     }
    129     return std::make_pair(begin() + I, false);
    130   }
    131 
    132   size_type count(const KeyT &Key) const {
    133     typename MapType::const_iterator Pos = Map.find(Key);
    134     return Pos == Map.end()? 0 : 1;
    135   }
    136 
    137   iterator find(const KeyT &Key) {
    138     typename MapType::const_iterator Pos = Map.find(Key);
    139     return Pos == Map.end()? Vector.end() :
    140                             (Vector.begin() + Pos->second);
    141   }
    142 
    143   const_iterator find(const KeyT &Key) const {
    144     typename MapType::const_iterator Pos = Map.find(Key);
    145     return Pos == Map.end()? Vector.end() :
    146                             (Vector.begin() + Pos->second);
    147   }
    148 
    149   /// \brief Remove the last element from the vector.
    150   void pop_back() {
    151     typename MapType::iterator Pos = Map.find(Vector.back().first);
    152     Map.erase(Pos);
    153     Vector.pop_back();
    154   }
    155 
    156   /// \brief Remove the element given by Iterator.
    157   ///
    158   /// Returns an iterator to the element following the one which was removed,
    159   /// which may be end().
    160   ///
    161   /// \note This is a deceivingly expensive operation (linear time).  It's
    162   /// usually better to use \a remove_if() if possible.
    163   typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
    164     Map.erase(Iterator->first);
    165     auto Next = Vector.erase(Iterator);
    166     if (Next == Vector.end())
    167       return Next;
    168 
    169     // Update indices in the map.
    170     size_t Index = Next - Vector.begin();
    171     for (auto &I : Map) {
    172       assert(I.second != Index && "Index was already erased!");
    173       if (I.second > Index)
    174         --I.second;
    175     }
    176     return Next;
    177   }
    178 
    179   /// \brief Remove all elements with the key value Key.
    180   ///
    181   /// Returns the number of elements removed.
    182   size_type erase(const KeyT &Key) {
    183     auto Iterator = find(Key);
    184     if (Iterator == end())
    185       return 0;
    186     erase(Iterator);
    187     return 1;
    188   }
    189 
    190   /// \brief Remove the elements that match the predicate.
    191   ///
    192   /// Erase all elements that match \c Pred in a single pass.  Takes linear
    193   /// time.
    194   template <class Predicate> void remove_if(Predicate Pred);
    195 };
    196 
    197 template <typename KeyT, typename ValueT, typename MapType, typename VectorType>
    198 template <class Function>
    199 void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
    200   auto O = Vector.begin();
    201   for (auto I = O, E = Vector.end(); I != E; ++I) {
    202     if (Pred(*I)) {
    203       // Erase from the map.
    204       Map.erase(I->first);
    205       continue;
    206     }
    207 
    208     if (I != O) {
    209       // Move the value and update the index in the map.
    210       *O = std::move(*I);
    211       Map[O->first] = O - Vector.begin();
    212     }
    213     ++O;
    214   }
    215   // Erase trailing entries in the vector.
    216   Vector.erase(O, Vector.end());
    217 }
    218 
    219 /// \brief A MapVector that performs no allocations if smaller than a certain
    220 /// size.
    221 template <typename KeyT, typename ValueT, unsigned N>
    222 struct SmallMapVector
    223     : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>,
    224                 SmallVector<std::pair<KeyT, ValueT>, N>> {
    225 };
    226 
    227 } // end namespace llvm
    228 
    229 #endif // LLVM_ADT_MAPVECTOR_H
    230