|  | //===--- StringMap.h - String Hash table map interface ----------*- 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 StringMap class. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_ADT_STRINGMAP_H | 
|  | #define LLVM_ADT_STRINGMAP_H | 
|  |  | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/Support/Allocator.h" | 
|  | #include "llvm/Support/PointerLikeTypeTraits.h" | 
|  | #include <cassert> | 
|  | #include <cstdint> | 
|  | #include <cstdlib> | 
|  | #include <cstring> | 
|  | #include <utility> | 
|  | #include <initializer_list> | 
|  | #include <new> | 
|  | #include <utility> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | template<typename ValueT> | 
|  | class StringMapConstIterator; | 
|  | template<typename ValueT> | 
|  | class StringMapIterator; | 
|  | template<typename ValueTy> | 
|  | class StringMapEntry; | 
|  |  | 
|  | /// StringMapEntryBase - Shared base class of StringMapEntry instances. | 
|  | class StringMapEntryBase { | 
|  | unsigned StrLen; | 
|  |  | 
|  | public: | 
|  | explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} | 
|  |  | 
|  | unsigned getKeyLength() const { return StrLen; } | 
|  | }; | 
|  |  | 
|  | /// StringMapImpl - This is the base class of StringMap that is shared among | 
|  | /// all of its instantiations. | 
|  | class StringMapImpl { | 
|  | protected: | 
|  | // Array of NumBuckets pointers to entries, null pointers are holes. | 
|  | // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed | 
|  | // by an array of the actual hash values as unsigned integers. | 
|  | StringMapEntryBase **TheTable; | 
|  | unsigned NumBuckets; | 
|  | unsigned NumItems; | 
|  | unsigned NumTombstones; | 
|  | unsigned ItemSize; | 
|  |  | 
|  | protected: | 
|  | explicit StringMapImpl(unsigned itemSize) | 
|  | : TheTable(nullptr), | 
|  | // Initialize the map with zero buckets to allocation. | 
|  | NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} | 
|  | StringMapImpl(StringMapImpl &&RHS) | 
|  | : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), | 
|  | NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), | 
|  | ItemSize(RHS.ItemSize) { | 
|  | RHS.TheTable = nullptr; | 
|  | RHS.NumBuckets = 0; | 
|  | RHS.NumItems = 0; | 
|  | RHS.NumTombstones = 0; | 
|  | } | 
|  |  | 
|  | StringMapImpl(unsigned InitSize, unsigned ItemSize); | 
|  | unsigned RehashTable(unsigned BucketNo = 0); | 
|  |  | 
|  | /// LookupBucketFor - Look up the bucket that the specified string should end | 
|  | /// up in.  If it already exists as a key in the map, the Item pointer for the | 
|  | /// specified bucket will be non-null.  Otherwise, it will be null.  In either | 
|  | /// case, the FullHashValue field of the bucket will be set to the hash value | 
|  | /// of the string. | 
|  | unsigned LookupBucketFor(StringRef Key); | 
|  |  | 
|  | /// FindKey - Look up the bucket that contains the specified key. If it exists | 
|  | /// in the map, return the bucket number of the key.  Otherwise return -1. | 
|  | /// This does not modify the map. | 
|  | int FindKey(StringRef Key) const; | 
|  |  | 
|  | /// RemoveKey - Remove the specified StringMapEntry from the table, but do not | 
|  | /// delete it.  This aborts if the value isn't in the table. | 
|  | void RemoveKey(StringMapEntryBase *V); | 
|  |  | 
|  | /// RemoveKey - Remove the StringMapEntry for the specified key from the | 
|  | /// table, returning it.  If the key is not in the table, this returns null. | 
|  | StringMapEntryBase *RemoveKey(StringRef Key); | 
|  |  | 
|  | /// Allocate the table with the specified number of buckets and otherwise | 
|  | /// setup the map as empty. | 
|  | void init(unsigned Size); | 
|  |  | 
|  | public: | 
|  | static StringMapEntryBase *getTombstoneVal() { | 
|  | uintptr_t Val = static_cast<uintptr_t>(-1); | 
|  | Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable; | 
|  | return reinterpret_cast<StringMapEntryBase *>(Val); | 
|  | } | 
|  |  | 
|  | unsigned getNumBuckets() const { return NumBuckets; } | 
|  | unsigned getNumItems() const { return NumItems; } | 
|  |  | 
|  | bool empty() const { return NumItems == 0; } | 
|  | unsigned size() const { return NumItems; } | 
|  |  | 
|  | void swap(StringMapImpl &Other) { | 
|  | std::swap(TheTable, Other.TheTable); | 
|  | std::swap(NumBuckets, Other.NumBuckets); | 
|  | std::swap(NumItems, Other.NumItems); | 
|  | std::swap(NumTombstones, Other.NumTombstones); | 
|  | } | 
|  | }; | 
|  |  | 
|  | /// StringMapEntry - This is used to represent one value that is inserted into | 
|  | /// a StringMap.  It contains the Value itself and the key: the string length | 
|  | /// and data. | 
|  | template<typename ValueTy> | 
|  | class StringMapEntry : public StringMapEntryBase { | 
|  | public: | 
|  | ValueTy second; | 
|  |  | 
|  | explicit StringMapEntry(unsigned strLen) | 
|  | : StringMapEntryBase(strLen), second() {} | 
|  | template <typename... InitTy> | 
|  | StringMapEntry(unsigned strLen, InitTy &&... InitVals) | 
|  | : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {} | 
|  | StringMapEntry(StringMapEntry &E) = delete; | 
|  |  | 
|  | StringRef getKey() const { | 
|  | return StringRef(getKeyData(), getKeyLength()); | 
|  | } | 
|  |  | 
|  | const ValueTy &getValue() const { return second; } | 
|  | ValueTy &getValue() { return second; } | 
|  |  | 
|  | void setValue(const ValueTy &V) { second = V; } | 
|  |  | 
|  | /// getKeyData - Return the start of the string data that is the key for this | 
|  | /// value.  The string data is always stored immediately after the | 
|  | /// StringMapEntry object. | 
|  | const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} | 
|  |  | 
|  | StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } | 
|  |  | 
|  | /// Create a StringMapEntry for the specified key construct the value using | 
|  | /// \p InitiVals. | 
|  | template <typename AllocatorTy, typename... InitTy> | 
|  | static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, | 
|  | InitTy &&... InitVals) { | 
|  | unsigned KeyLength = Key.size(); | 
|  |  | 
|  | // Allocate a new item with space for the string at the end and a null | 
|  | // terminator. | 
|  | unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ | 
|  | KeyLength+1; | 
|  | unsigned Alignment = alignof(StringMapEntry); | 
|  |  | 
|  | StringMapEntry *NewItem = | 
|  | static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); | 
|  |  | 
|  | // Construct the value. | 
|  | new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...); | 
|  |  | 
|  | // Copy the string information. | 
|  | char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); | 
|  | if (KeyLength > 0) | 
|  | memcpy(StrBuffer, Key.data(), KeyLength); | 
|  | StrBuffer[KeyLength] = 0;  // Null terminate for convenience of clients. | 
|  | return NewItem; | 
|  | } | 
|  |  | 
|  | /// Create - Create a StringMapEntry with normal malloc/free. | 
|  | template <typename... InitType> | 
|  | static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) { | 
|  | MallocAllocator A; | 
|  | return Create(Key, A, std::forward<InitType>(InitVal)...); | 
|  | } | 
|  |  | 
|  | static StringMapEntry *Create(StringRef Key) { | 
|  | return Create(Key, ValueTy()); | 
|  | } | 
|  |  | 
|  | /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded | 
|  | /// into a StringMapEntry, return the StringMapEntry itself. | 
|  | static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { | 
|  | char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>); | 
|  | return *reinterpret_cast<StringMapEntry*>(Ptr); | 
|  | } | 
|  |  | 
|  | /// Destroy - Destroy this StringMapEntry, releasing memory back to the | 
|  | /// specified allocator. | 
|  | template<typename AllocatorTy> | 
|  | void Destroy(AllocatorTy &Allocator) { | 
|  | // Free memory referenced by the item. | 
|  | unsigned AllocSize = | 
|  | static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1; | 
|  | this->~StringMapEntry(); | 
|  | Allocator.Deallocate(static_cast<void *>(this), AllocSize); | 
|  | } | 
|  |  | 
|  | /// Destroy this object, releasing memory back to the malloc allocator. | 
|  | void Destroy() { | 
|  | MallocAllocator A; | 
|  | Destroy(A); | 
|  | } | 
|  | }; | 
|  |  | 
|  | /// StringMap - This is an unconventional map that is specialized for handling | 
|  | /// keys that are "strings", which are basically ranges of bytes. This does some | 
|  | /// funky memory allocation and hashing things to make it extremely efficient, | 
|  | /// storing the string data *after* the value in the map. | 
|  | template<typename ValueTy, typename AllocatorTy = MallocAllocator> | 
|  | class StringMap : public StringMapImpl { | 
|  | AllocatorTy Allocator; | 
|  |  | 
|  | public: | 
|  | typedef StringMapEntry<ValueTy> MapEntryTy; | 
|  |  | 
|  | StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} | 
|  | explicit StringMap(unsigned InitialSize) | 
|  | : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} | 
|  |  | 
|  | explicit StringMap(AllocatorTy A) | 
|  | : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} | 
|  |  | 
|  | StringMap(unsigned InitialSize, AllocatorTy A) | 
|  | : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), | 
|  | Allocator(A) {} | 
|  |  | 
|  | StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List) | 
|  | : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) { | 
|  | for (const auto &P : List) { | 
|  | insert(P); | 
|  | } | 
|  | } | 
|  |  | 
|  | StringMap(StringMap &&RHS) | 
|  | : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} | 
|  |  | 
|  | StringMap &operator=(StringMap RHS) { | 
|  | StringMapImpl::swap(RHS); | 
|  | std::swap(Allocator, RHS.Allocator); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | StringMap(const StringMap &RHS) : | 
|  | StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), | 
|  | Allocator(RHS.Allocator) { | 
|  | if (RHS.empty()) | 
|  | return; | 
|  |  | 
|  | // Allocate TheTable of the same size as RHS's TheTable, and set the | 
|  | // sentinel appropriately (and NumBuckets). | 
|  | init(RHS.NumBuckets); | 
|  | unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1), | 
|  | *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1); | 
|  |  | 
|  | NumItems = RHS.NumItems; | 
|  | NumTombstones = RHS.NumTombstones; | 
|  | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { | 
|  | StringMapEntryBase *Bucket = RHS.TheTable[I]; | 
|  | if (!Bucket || Bucket == getTombstoneVal()) { | 
|  | TheTable[I] = Bucket; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | TheTable[I] = MapEntryTy::Create( | 
|  | static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator, | 
|  | static_cast<MapEntryTy *>(Bucket)->getValue()); | 
|  | HashTable[I] = RHSHashTable[I]; | 
|  | } | 
|  |  | 
|  | // Note that here we've copied everything from the RHS into this object, | 
|  | // tombstones included. We could, instead, have re-probed for each key to | 
|  | // instantiate this new object without any tombstone buckets. The | 
|  | // assumption here is that items are rarely deleted from most StringMaps, | 
|  | // and so tombstones are rare, so the cost of re-probing for all inputs is | 
|  | // not worthwhile. | 
|  | } | 
|  |  | 
|  | AllocatorTy &getAllocator() { return Allocator; } | 
|  | const AllocatorTy &getAllocator() const { return Allocator; } | 
|  |  | 
|  | typedef const char* key_type; | 
|  | typedef ValueTy mapped_type; | 
|  | typedef StringMapEntry<ValueTy> value_type; | 
|  | typedef size_t size_type; | 
|  |  | 
|  | typedef StringMapConstIterator<ValueTy> const_iterator; | 
|  | typedef StringMapIterator<ValueTy> iterator; | 
|  |  | 
|  | iterator begin() { | 
|  | return iterator(TheTable, NumBuckets == 0); | 
|  | } | 
|  | iterator end() { | 
|  | return iterator(TheTable+NumBuckets, true); | 
|  | } | 
|  | const_iterator begin() const { | 
|  | return const_iterator(TheTable, NumBuckets == 0); | 
|  | } | 
|  | const_iterator end() const { | 
|  | return const_iterator(TheTable+NumBuckets, true); | 
|  | } | 
|  |  | 
|  | iterator find(StringRef Key) { | 
|  | int Bucket = FindKey(Key); | 
|  | if (Bucket == -1) return end(); | 
|  | return iterator(TheTable+Bucket, true); | 
|  | } | 
|  |  | 
|  | const_iterator find(StringRef Key) const { | 
|  | int Bucket = FindKey(Key); | 
|  | if (Bucket == -1) return end(); | 
|  | return const_iterator(TheTable+Bucket, true); | 
|  | } | 
|  |  | 
|  | /// lookup - Return the entry for the specified key, or a default | 
|  | /// constructed value if no such entry exists. | 
|  | ValueTy lookup(StringRef Key) const { | 
|  | const_iterator it = find(Key); | 
|  | if (it != end()) | 
|  | return it->second; | 
|  | return ValueTy(); | 
|  | } | 
|  |  | 
|  | /// Lookup the ValueTy for the \p Key, or create a default constructed value | 
|  | /// if the key is not in the map. | 
|  | ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; } | 
|  |  | 
|  | /// count - Return 1 if the element is in the map, 0 otherwise. | 
|  | size_type count(StringRef Key) const { | 
|  | return find(Key) == end() ? 0 : 1; | 
|  | } | 
|  |  | 
|  | /// insert - Insert the specified key/value pair into the map.  If the key | 
|  | /// already exists in the map, return false and ignore the request, otherwise | 
|  | /// insert it and return true. | 
|  | bool insert(MapEntryTy *KeyValue) { | 
|  | unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); | 
|  | StringMapEntryBase *&Bucket = TheTable[BucketNo]; | 
|  | if (Bucket && Bucket != getTombstoneVal()) | 
|  | return false;  // Already exists in map. | 
|  |  | 
|  | if (Bucket == getTombstoneVal()) | 
|  | --NumTombstones; | 
|  | Bucket = KeyValue; | 
|  | ++NumItems; | 
|  | assert(NumItems + NumTombstones <= NumBuckets); | 
|  |  | 
|  | RehashTable(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /// insert - Inserts the specified key/value pair into the map if the key | 
|  | /// isn't already in the map. The bool component of the returned pair is true | 
|  | /// if and only if the insertion takes place, and the iterator component of | 
|  | /// the pair points to the element with key equivalent to the key of the pair. | 
|  | std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) { | 
|  | return try_emplace(KV.first, std::move(KV.second)); | 
|  | } | 
|  |  | 
|  | /// Emplace a new element for the specified key into the map if the key isn't | 
|  | /// already in the map. The bool component of the returned pair is true | 
|  | /// if and only if the insertion takes place, and the iterator component of | 
|  | /// the pair points to the element with key equivalent to the key of the pair. | 
|  | template <typename... ArgsTy> | 
|  | std::pair<iterator, bool> try_emplace(StringRef Key, ArgsTy &&... Args) { | 
|  | unsigned BucketNo = LookupBucketFor(Key); | 
|  | StringMapEntryBase *&Bucket = TheTable[BucketNo]; | 
|  | if (Bucket && Bucket != getTombstoneVal()) | 
|  | return std::make_pair(iterator(TheTable + BucketNo, false), | 
|  | false); // Already exists in map. | 
|  |  | 
|  | if (Bucket == getTombstoneVal()) | 
|  | --NumTombstones; | 
|  | Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...); | 
|  | ++NumItems; | 
|  | assert(NumItems + NumTombstones <= NumBuckets); | 
|  |  | 
|  | BucketNo = RehashTable(BucketNo); | 
|  | return std::make_pair(iterator(TheTable + BucketNo, false), true); | 
|  | } | 
|  |  | 
|  | // clear - Empties out the StringMap | 
|  | void clear() { | 
|  | if (empty()) return; | 
|  |  | 
|  | // Zap all values, resetting the keys back to non-present (not tombstone), | 
|  | // which is safe because we're removing all elements. | 
|  | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { | 
|  | StringMapEntryBase *&Bucket = TheTable[I]; | 
|  | if (Bucket && Bucket != getTombstoneVal()) { | 
|  | static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); | 
|  | } | 
|  | Bucket = nullptr; | 
|  | } | 
|  |  | 
|  | NumItems = 0; | 
|  | NumTombstones = 0; | 
|  | } | 
|  |  | 
|  | /// remove - Remove the specified key/value pair from the map, but do not | 
|  | /// erase it.  This aborts if the key is not in the map. | 
|  | void remove(MapEntryTy *KeyValue) { | 
|  | RemoveKey(KeyValue); | 
|  | } | 
|  |  | 
|  | void erase(iterator I) { | 
|  | MapEntryTy &V = *I; | 
|  | remove(&V); | 
|  | V.Destroy(Allocator); | 
|  | } | 
|  |  | 
|  | bool erase(StringRef Key) { | 
|  | iterator I = find(Key); | 
|  | if (I == end()) return false; | 
|  | erase(I); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | ~StringMap() { | 
|  | // Delete all the elements in the map, but don't reset the elements | 
|  | // to default values.  This is a copy of clear(), but avoids unnecessary | 
|  | // work not required in the destructor. | 
|  | if (!empty()) { | 
|  | for (unsigned I = 0, E = NumBuckets; I != E; ++I) { | 
|  | StringMapEntryBase *Bucket = TheTable[I]; | 
|  | if (Bucket && Bucket != getTombstoneVal()) { | 
|  | static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); | 
|  | } | 
|  | } | 
|  | } | 
|  | free(TheTable); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename ValueTy> class StringMapConstIterator { | 
|  | protected: | 
|  | StringMapEntryBase **Ptr = nullptr; | 
|  |  | 
|  | public: | 
|  | typedef StringMapEntry<ValueTy> value_type; | 
|  |  | 
|  | StringMapConstIterator() = default; | 
|  |  | 
|  | explicit StringMapConstIterator(StringMapEntryBase **Bucket, | 
|  | bool NoAdvance = false) | 
|  | : Ptr(Bucket) { | 
|  | if (!NoAdvance) AdvancePastEmptyBuckets(); | 
|  | } | 
|  |  | 
|  | const value_type &operator*() const { | 
|  | return *static_cast<StringMapEntry<ValueTy>*>(*Ptr); | 
|  | } | 
|  | const value_type *operator->() const { | 
|  | return static_cast<StringMapEntry<ValueTy>*>(*Ptr); | 
|  | } | 
|  |  | 
|  | bool operator==(const StringMapConstIterator &RHS) const { | 
|  | return Ptr == RHS.Ptr; | 
|  | } | 
|  | bool operator!=(const StringMapConstIterator &RHS) const { | 
|  | return Ptr != RHS.Ptr; | 
|  | } | 
|  |  | 
|  | inline StringMapConstIterator& operator++() {   // Preincrement | 
|  | ++Ptr; | 
|  | AdvancePastEmptyBuckets(); | 
|  | return *this; | 
|  | } | 
|  | StringMapConstIterator operator++(int) {        // Postincrement | 
|  | StringMapConstIterator tmp = *this; ++*this; return tmp; | 
|  | } | 
|  |  | 
|  | private: | 
|  | void AdvancePastEmptyBuckets() { | 
|  | while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) | 
|  | ++Ptr; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<typename ValueTy> | 
|  | class StringMapIterator : public StringMapConstIterator<ValueTy> { | 
|  | public: | 
|  | StringMapIterator() = default; | 
|  |  | 
|  | explicit StringMapIterator(StringMapEntryBase **Bucket, | 
|  | bool NoAdvance = false) | 
|  | : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { | 
|  | } | 
|  |  | 
|  | StringMapEntry<ValueTy> &operator*() const { | 
|  | return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); | 
|  | } | 
|  | StringMapEntry<ValueTy> *operator->() const { | 
|  | return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif // LLVM_ADT_STRINGMAP_H |