//===--- BlotMapVector.h - Map vector with "blot" operation ----*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_BLOTMAPVECTOR_H #define SWIFT_BASIC_BLOTMAPVECTOR_H #include "swift/Basic/LLVM.h" #include "swift/Basic/Range.h" #include "llvm/ADT/DenseMap.h" #include #include namespace swift { template bool compareKeyAgainstDefaultKey(const std::pair &Pair) { return Pair.first == KeyT(); } /// An associative container with fast insertion-order (deterministic) /// iteration over its elements. Plus the special blot operation. template , typename VectorT = std::vector>>> class BlotMapVector { /// Map keys to indices in Vector. MapT Map; /// Keys and values. VectorT Vector; public: using iterator = typename VectorT::iterator; using const_iterator = typename VectorT::const_iterator; using key_type = KeyT; using mapped_type = ValueT; iterator begin() { return Vector.begin(); } iterator end() { return Vector.end(); } const_iterator begin() const { return Vector.begin(); } const_iterator end() const { return Vector.end(); } iterator_range getItems() { return swift::make_range(begin(), end()); } iterator_range getItems() const { return swift::make_range(begin(), end()); } ValueT &operator[](const KeyT &Arg) { auto 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].value().second; } template std::pair try_emplace(KeyT &&Key, Ts &&... Args) { auto Pair = Map.insert(std::make_pair(std::move(Key), size_t(0))); if (!Pair.second) { return std::make_pair(Vector.begin() + Pair.first->second, false); } size_t Num = Vector.size(); Pair.first->second = Num; Vector.emplace_back( std::make_pair(Pair.first->first, ValueT(std::forward(Args)...))); return std::make_pair(Vector.begin() + Num, true); } template std::pair try_emplace(const KeyT &Key, Ts &&... Args) { auto Pair = Map.insert(std::make_pair(std::move(Key), size_t(0))); if (!Pair.second) { return std::make_pair(Vector.begin() + Pair.first->second, false); } size_t Num = Vector.size(); Pair.first->second = Num; Vector.emplace_back( std::make_pair(Pair.first->first, ValueT(std::forward(Args)...))); return std::make_pair(Vector.begin() + Num, true); } std::pair insert(std::pair &InsertPair) { return try_emplace(InsertPair.first, InsertPair.second); } std::pair insert(const std::pair &InsertPair) { return try_emplace(InsertPair.first, InsertPair.second); } iterator find(const KeyT &Key) { typename MapT::iterator It = Map.find(Key); if (It == Map.end()) return Vector.end(); auto Iter = Vector.begin() + It->second; if (!Iter->has_value()) return Vector.end(); return Iter; } const_iterator find(const KeyT &Key) const { return const_cast(*this).find(Key); } /// Eliminate the element at `Key`. Instead of removing the element from the /// vector, just zero out the key in the vector. This leaves iterators /// intact, but clients must be prepared for zeroed-out keys when iterating. /// /// Return true if the element was found and erased. bool erase(const KeyT &Key) { typename MapT::iterator It = Map.find(Key); if (It == Map.end()) return false; Vector[It->second] = std::nullopt; Map.erase(It); return true; } /// Eliminate the element at the given iterator. Instead of removing the /// element from the vector, just zero out the key in the vector. This /// leaves iterators intact, but clients must be prepared for zeroed-out /// keys when iterating. void erase(iterator I) { erase((*I)->first); } void clear() { Map.clear(); Vector.clear(); } unsigned size() const { return Map.size(); } ValueT lookup(const KeyT &Val) const { auto Iter = Map.find(Val); if (Iter == Map.end()) return ValueT(); auto &P = Vector[Iter->second]; if (!P.has_value()) return ValueT(); return P->second; } size_t count(const KeyT &Val) const { return Map.count(Val); } bool empty() const { return Map.empty(); } }; template , typename VectorT = llvm::SmallVector>, N>> class SmallBlotMapVector : public BlotMapVector { public: SmallBlotMapVector() {} }; } // end namespace swift #endif // SWIFT_BASIC_BLOTMAPVECTOR_H