LLVM API Documentation

MapVector.h
Go to the documentation of this file.
00001 //===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements a map that provides insertion order iteration. The
00011 // interface is purposefully minimal. The key is assumed to be cheap to copy
00012 // and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
00013 // a std::vector.
00014 //
00015 //===----------------------------------------------------------------------===//
00016 
00017 #ifndef LLVM_ADT_MAPVECTOR_H
00018 #define LLVM_ADT_MAPVECTOR_H
00019 
00020 #include "llvm/ADT/DenseMap.h"
00021 #include <vector>
00022 
00023 namespace llvm {
00024 
00025 /// This class implements a map that also provides access to all stored values
00026 /// in a deterministic order. The values are kept in a std::vector and the
00027 /// mapping is done with DenseMap from Keys to indexes in that vector.
00028 template<typename KeyT, typename ValueT,
00029          typename MapType = llvm::DenseMap<KeyT, unsigned>,
00030          typename VectorType = std::vector<std::pair<KeyT, ValueT> > >
00031 class MapVector {
00032   typedef typename VectorType::size_type size_type;
00033 
00034   MapType Map;
00035   VectorType Vector;
00036 
00037 public:
00038   typedef typename VectorType::iterator iterator;
00039   typedef typename VectorType::const_iterator const_iterator;
00040 
00041   size_type size() const {
00042     return Vector.size();
00043   }
00044 
00045   iterator begin() {
00046     return Vector.begin();
00047   }
00048 
00049   const_iterator begin() const {
00050     return Vector.begin();
00051   }
00052 
00053   iterator end() {
00054     return Vector.end();
00055   }
00056 
00057   const_iterator end() const {
00058     return Vector.end();
00059   }
00060 
00061   bool empty() const {
00062     return Vector.empty();
00063   }
00064 
00065   std::pair<KeyT, ValueT>       &front()       { return Vector.front(); }
00066   const std::pair<KeyT, ValueT> &front() const { return Vector.front(); }
00067   std::pair<KeyT, ValueT>       &back()        { return Vector.back(); }
00068   const std::pair<KeyT, ValueT> &back()  const { return Vector.back(); }
00069 
00070   void clear() {
00071     Map.clear();
00072     Vector.clear();
00073   }
00074 
00075   ValueT &operator[](const KeyT &Key) {
00076     std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
00077     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
00078     unsigned &I = Result.first->second;
00079     if (Result.second) {
00080       Vector.push_back(std::make_pair(Key, ValueT()));
00081       I = Vector.size() - 1;
00082     }
00083     return Vector[I].second;
00084   }
00085 
00086   ValueT lookup(const KeyT &Key) const {
00087     typename MapType::const_iterator Pos = Map.find(Key);
00088     return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
00089   }
00090 
00091   std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
00092     std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
00093     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
00094     unsigned &I = Result.first->second;
00095     if (Result.second) {
00096       Vector.push_back(std::make_pair(KV.first, KV.second));
00097       I = Vector.size() - 1;
00098       return std::make_pair(std::prev(end()), true);
00099     }
00100     return std::make_pair(begin() + I, false);
00101   }
00102 
00103   size_type count(const KeyT &Key) const {
00104     typename MapType::const_iterator Pos = Map.find(Key);
00105     return Pos == Map.end()? 0 : 1;
00106   }
00107 
00108   iterator find(const KeyT &Key) {
00109     typename MapType::const_iterator Pos = Map.find(Key);
00110     return Pos == Map.end()? Vector.end() :
00111                             (Vector.begin() + Pos->second);
00112   }
00113 
00114   const_iterator find(const KeyT &Key) const {
00115     typename MapType::const_iterator Pos = Map.find(Key);
00116     return Pos == Map.end()? Vector.end() :
00117                             (Vector.begin() + Pos->second);
00118   }
00119 
00120   /// \brief Remove the last element from the vector.
00121   void pop_back() {
00122     typename MapType::iterator Pos = Map.find(Vector.back().first);
00123     Map.erase(Pos);
00124     Vector.pop_back();
00125   }
00126 
00127   /// \brief Remove the element given by Iterator.
00128   ///
00129   /// Returns an iterator to the element following the one which was removed,
00130   /// which may be end().
00131   ///
00132   /// \note This is a deceivingly expensive operation (linear time).  It's
00133   /// usually better to use \a remove_if() if possible.
00134   typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
00135     Map.erase(Iterator->first);
00136     auto Next = Vector.erase(Iterator);
00137     if (Next == Vector.end())
00138       return Next;
00139 
00140     // Update indices in the map.
00141     size_t Index = Next - Vector.begin();
00142     for (auto &I : Map) {
00143       assert(I.second != Index && "Index was already erased!");
00144       if (I.second > Index)
00145         --I.second;
00146     }
00147     return Next;
00148   }
00149 
00150   /// \brief Remove the elements that match the predicate.
00151   ///
00152   /// Erase all elements that match \c Pred in a single pass.  Takes linear
00153   /// time.
00154   template <class Predicate> void remove_if(Predicate Pred);
00155 };
00156 
00157 template <typename KeyT, typename ValueT, typename MapType, typename VectorType>
00158 template <class Function>
00159 void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
00160   auto O = Vector.begin();
00161   for (auto I = O, E = Vector.end(); I != E; ++I) {
00162     if (Pred(*I)) {
00163       // Erase from the map.
00164       Map.erase(I->first);
00165       continue;
00166     }
00167 
00168     if (I != O) {
00169       // Move the value and update the index in the map.
00170       *O = std::move(*I);
00171       Map[O->first] = O - Vector.begin();
00172     }
00173     ++O;
00174   }
00175   // Erase trailing entries in the vector.
00176   Vector.erase(O, Vector.end());
00177 }
00178 
00179 } // end namespace llvm
00180 
00181 #endif