//===- llvm/ADT/MultiImplMap.h - 'Normally small' pointer set ----*- C++ -*-==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the MultiImplMap class. // MultiImplMap presents map container interface. // It has two modes, one for small amount of elements and one for big amount. // User should set map implementation for both of them. User also should // set the maximum possible number of elements for small mode. // If user want to use MultiImplMap instead of DenseMap, he should pass // DenseMapCompatible = true. Note that in this case map implementations should // present additional DenseMap specific methods (see below). // Initially MultiImplMap uses small mode and small map implementation. // It triggered to the big mode when number of contained elements exceeds // maximum possible elements for small mode. // // Types that should be defined in nested map class: // // key_type; // mapped_type; // value_type; // std::pair // // or std::pair // iterator; // const_iterator; // // Map implementation should provide the next interface: // // // Constructors // (default constructor) // (copy constructor) // // // Size // unsigned size() const; // bool empty() const; // // // Iterators // iterator begin(); // const_iterator begin(); // iterator end(); // const_iterator end(); // // // Modifiers // void clear(); // std::pair insert(const value_type& KV); // template // void insert(IterT I, IterT E); // void erase(key_type K); // void erase(iterator i); // void swap(MultiImplMap& rhs); // // // Search operations // iterator find(const key_type& K); // const_iterator find(const key_type& K) const; // bool count(const key_type& K) const; // mapped_type &operator[](const key_type &Key); // // // Other operations // self& operator=(const self& other); // // // If DenseMapCompatible == true, you also should present next methods. // // See DenseMap comments for more details about its behavior. // bool isPointerIntoBucketsArray(const void *Ptr) const; // const void *getPointerIntoBucketsArray() const; // value_type& FindAndConstruct(const key_type &Key); // // The list of methods that should be implemented in nested map iterator class: // // (conversion constructor from non-constant iterator) // // bool operator==(const const_iterator& rhs) const; // bool operator!=(const const_iterator& rhs) const; // reference operator*() const; // pointer operator->() const; // inline self& operator++(); // // //===----------------------------------------------------------------------===// #ifndef MULTIIMPLEMENTATIONMAP_H_ #define MULTIIMPLEMENTATIONMAP_H_ #include #include #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FlatArrayMap.h" #include "llvm/Support/type_traits.h" namespace llvm { template class MultiImplMapIterator; template struct MultiImplMapIteratorsFactory; template struct MultiImplMapTypes { typedef typename SmallMapTy::key_type key_type; typedef typename SmallMapTy::mapped_type mapped_type; typedef typename std::pair value_type; }; //===--------------------------------------------------------------------===// /// MultiImplMap is map that has two modes, one for small amount of /// elements and one for big amount. /// User should set map implementation for both of them. User also should /// set the maximum possible number of elements for small mode. /// If user want to use MultiImplMap instead of DenseMap, he should pass /// DenseMapCompatible = true. /// Initially MultiImplMap uses small mode and small map implementation. /// It triggered to the big mode when number of contained elements exceeds /// maximum possible elements for small mode. template > class MultiImplMap { protected: SmallMapTy SmallMap; BigMapTy BigMap; bool UseSmall; enum { MaxSmallSize = MaxSmallN }; public: typedef MultiImplMapTypes Types; typedef typename Types::key_type key_type; typedef typename Types::mapped_type mapped_type; typedef typename Types::value_type value_type; typedef typename ItFactory::iterator iterator; typedef typename ItFactory::const_iterator const_iterator; typedef std::pair ins_res; typedef typename std::pair small_ins_res; typedef typename std::pair big_ins_res; typedef MultiImplMap self; MultiImplMap() : UseSmall(true) {} MultiImplMap(const self& other) { if (other.UseSmall) { SmallMap = other.SmallMap; UseSmall = true; } else { if (other.size() <= MaxSmallN) { SmallMap.insert(other.BigMap.begin(), other.BigMap.end()); UseSmall = true; } else { BigMap = other.BigMap; UseSmall = false; } } } // Size unsigned size() const { if (UseSmall) return SmallMap.size(); return BigMap.size(); } bool empty() const { if (UseSmall) return SmallMap.empty(); return BigMap.empty(); } // Iterators iterator begin() { if (UseSmall) return ItFactory::begin(SmallMap); return ItFactory::begin(BigMap); } const_iterator begin() const { if (UseSmall) return ItFactory::begin(SmallMap); return ItFactory::begin(BigMap); } iterator end() { if (UseSmall) return ItFactory::end(SmallMap); return ItFactory::end(BigMap); } const_iterator end() const { if (UseSmall) return ItFactory::end(SmallMap); return ItFactory::end(BigMap); } // Modifiers void clear() { if (UseSmall) SmallMap.clear(); else BigMap.clear(); } std::pair insert(const value_type& KV) { if (UseSmall) { if (SmallMap.size() < MaxSmallSize) { small_ins_res Res = SmallMap.insert(KV); return std::make_pair(ItFactory::it(SmallMap, Res.first), Res.second); } // Move all to big map. BigMap.insert(SmallMap.begin(), SmallMap.end()); SmallMap.clear(); UseSmall = false; } big_ins_res Res = BigMap.insert(KV); return std::make_pair(ItFactory::it(BigMap, Res.first), Res.second); } template std::pair insert(const OtherValTy& OtherKV) { const value_type* KV = reinterpret_cast( reinterpret_cast(OtherKV)); return insert(*KV); } template void insert(IterT I, IterT E) { for (; I != E; ++I) insert(*I); } void erase(key_type K) { if (UseSmall) SmallMap.erase(K); else BigMap.erase(K); } void erase(iterator i) { erase(i->first); } void swap(MultiImplMap& rhs) { SmallMap.swap(rhs.SmallMap); BigMap.swap(rhs.BigMap); std::swap(UseSmall, rhs.UseSmall); } // Search operations iterator find(const key_type& K) { if (UseSmall) return ItFactory::it(SmallMap, SmallMap.find(K)); return ItFactory::it(BigMap, BigMap.find(K)); } const_iterator find(const key_type& K) const { if (UseSmall) return ItFactory::const_it(SmallMap, SmallMap.find(K)); return ItFactory::const_it(BigMap, BigMap.find(K)); } bool count(const key_type& K) const { return find(K) != end(); } mapped_type &operator[](const key_type &Key) { ins_res res = insert(std::make_pair(Key, mapped_type())); return res.first->second; } // Other operations self& operator=(const self& other) { if (other.isSmall()) { SmallMap = other.SmallMap; if (!UseSmall) { BigMap.clear(); UseSmall = true; } return *this; } if (UseSmall) { SmallMap.clear(); UseSmall = false; } BigMap = other.BigMap; return *this; } // Utilities bool isSmall()const { return UseSmall; } SmallMapTy& getSmallMap() { return SmallMap; } const SmallMapTy& getSmallMap() const { return SmallMap; } BigMapTy& getBigMap() { return BigMap; } const BigMapTy& getBigMap() const { return BigMap; } }; template class MultiImplMap : public MultiImplMap { public: typedef MultiImplMap ParentTy; typedef typename ParentTy::Types Types; typedef typename Types::key_type key_type; typedef typename Types::mapped_type mapped_type; typedef typename Types::value_type value_type; typedef typename ParentTy::iterator iterator; /// isPointerIntoBucketsArray - Return true if the specified pointer points /// somewhere into the DenseMap's array of buckets (i.e. either to a key or /// value). bool isPointerIntoBucketsArray(const void *Ptr) const { if (this->UseSmall) return this->SmallMap.isPointerIntoBucketsArray(Ptr); return this->BigMap.isPointerIntoBucketsArray(Ptr); } /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets /// array. In conjunction with the previous method, this can be used to /// determine whether an insertion caused the map to reallocate data. const void *getPointerIntoBucketsArray() const { if (this->UseSmall) return this->SmallMap.getPointerIntoBucketsArray(); return this->BigMap.getPointerIntoBucketsArray(); } value_type& FindAndConstruct(const key_type &Key) { std::pair Res = this->insert(std::make_pair(Key, mapped_type())); return *Res.first; } }; template class MultiImplMapIterator { public: typedef MultiImplMapTypes Types; typedef typename Types::mapped_type mapped_type; typedef typename conditional::type value_type; typedef typename conditional::type small_iterator; typedef typename conditional::type big_iterator; typedef typename conditional::type void_ptr_ty; typedef value_type *pointer; typedef value_type &reference; typedef MultiImplMapIterator self; typedef MultiImplMapIterator non_const_self; typedef MultiImplMapIterator const_self; friend class MultiImplMapIterator; friend class MultiImplMapIterator; protected: template static value_type* toValueTypePtr(OtherValTy& ValTyRef) { return reinterpret_cast( reinterpret_cast(&ValTyRef)); } template static value_type& toValueTypeRef(OtherValTy& ValTyRef) { return *reinterpret_cast( reinterpret_cast(&ValTyRef)); } small_iterator SmallIt; big_iterator BigIt; bool UseSmall; public: MultiImplMapIterator() : UseSmall(true) {} MultiImplMapIterator(small_iterator It) : SmallIt(It), UseSmall(true) {} MultiImplMapIterator(big_iterator It) : BigIt(It), UseSmall(false) {} MultiImplMapIterator(const non_const_self& src) : SmallIt(src.SmallIt), BigIt(src.BigIt), UseSmall(src.UseSmall) {} bool operator==(const const_self& rhs) const { if (UseSmall != rhs.UseSmall) return false; if (UseSmall) return SmallIt == rhs.SmallIt; return BigIt == rhs.BigIt; } bool operator!=(const const_self& rhs) const { if (UseSmall != rhs.UseSmall) return true; if (UseSmall) return SmallIt != rhs.SmallIt; return BigIt != rhs.BigIt; } reference operator*() const { return UseSmall ? toValueTypeRef(*SmallIt) : toValueTypeRef(*BigIt);; } pointer operator->() const { return UseSmall ? toValueTypePtr(*SmallIt) : toValueTypePtr(*BigIt); } // Preincrement inline self& operator++() { if (UseSmall) ++SmallIt; return *this; } // Postincrement self operator++(int) { self tmp = *this; ++*this; return tmp; } }; template struct MultiImplMapIteratorsFactory { typedef MultiImplMapIterator iterator; typedef MultiImplMapIterator const_iterator; template static iterator it(MapImpl& impl, ItTy it) { return iterator(it); } template static const_iterator const_it(const MapImpl& impl, ConstItTy it) { return const_iterator(it); } template static iterator begin(MapImpl& impl) { return iterator(impl.begin()); } template static const_iterator begin(const MapImpl& impl) { return const_iterator(impl.begin()); } template static iterator end(MapImpl& impl) { return iterator(impl.end()); } template static const_iterator end(const MapImpl& impl) { return const_iterator(impl.end()); } }; template struct MultiImplMapIteratorsFactory< FlatArrayMap, DenseMap > { typedef FlatArrayMap SmallMapTy; typedef DenseMap BigMapTy; typedef DenseMapIterator iterator; typedef DenseMapIterator const_iterator; static iterator it(SmallMapTy& impl, typename SmallMapTy::iterator it) { return iterator(&(*it), &(*impl.end())); } static const_iterator const_it( const SmallMapTy& impl, typename SmallMapTy::const_iterator it) { return const_iterator(&(*it), &(*impl.end())); } static iterator it(BigMapTy& impl, typename BigMapTy::iterator it) { return it; } static const_iterator const_it( const BigMapTy& impl, typename BigMapTy::const_iterator it) { return it; } static iterator begin(SmallMapTy& impl) { return it(impl, impl.begin()); } static const_iterator begin(const SmallMapTy& impl) { return it(impl, impl.begin()); } static iterator begin(BigMapTy& impl) { return impl.begin(); } static const_iterator begin(const BigMapTy& impl) { return impl.begin(); } static iterator end(SmallMapTy& impl) { return it(impl, impl.end()); } static const_iterator end(const SmallMapTy& impl) { return const_it(impl, impl.end()); } static iterator end(BigMapTy& impl) { return impl.end(); } static const_iterator end(const BigMapTy& impl) { return impl.end(); } }; } #endif /* MULTIIMPLEMENTATIONMAP_H_ */