Home | History | Annotate | Download | only in ADT
      1 //===--- StringMap.h - String Hash table map interface ----------*- 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 defines the StringMap class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_ADT_STRINGMAP_H
     15 #define LLVM_ADT_STRINGMAP_H
     16 
     17 #include "llvm/ADT/StringRef.h"
     18 #include "llvm/Support/Allocator.h"
     19 #include "llvm/Support/PointerLikeTypeTraits.h"
     20 #include <cassert>
     21 #include <cstdint>
     22 #include <cstdlib>
     23 #include <cstring>
     24 #include <utility>
     25 #include <initializer_list>
     26 #include <new>
     27 #include <utility>
     28 
     29 namespace llvm {
     30 
     31   template<typename ValueT>
     32   class StringMapConstIterator;
     33   template<typename ValueT>
     34   class StringMapIterator;
     35   template<typename ValueTy>
     36   class StringMapEntry;
     37 
     38 /// StringMapEntryBase - Shared base class of StringMapEntry instances.
     39 class StringMapEntryBase {
     40   unsigned StrLen;
     41 
     42 public:
     43   explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
     44 
     45   unsigned getKeyLength() const { return StrLen; }
     46 };
     47 
     48 /// StringMapImpl - This is the base class of StringMap that is shared among
     49 /// all of its instantiations.
     50 class StringMapImpl {
     51 protected:
     52   // Array of NumBuckets pointers to entries, null pointers are holes.
     53   // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
     54   // by an array of the actual hash values as unsigned integers.
     55   StringMapEntryBase **TheTable;
     56   unsigned NumBuckets;
     57   unsigned NumItems;
     58   unsigned NumTombstones;
     59   unsigned ItemSize;
     60 
     61 protected:
     62   explicit StringMapImpl(unsigned itemSize)
     63       : TheTable(nullptr),
     64         // Initialize the map with zero buckets to allocation.
     65         NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {}
     66   StringMapImpl(StringMapImpl &&RHS)
     67       : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
     68         NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
     69         ItemSize(RHS.ItemSize) {
     70     RHS.TheTable = nullptr;
     71     RHS.NumBuckets = 0;
     72     RHS.NumItems = 0;
     73     RHS.NumTombstones = 0;
     74   }
     75 
     76   StringMapImpl(unsigned InitSize, unsigned ItemSize);
     77   unsigned RehashTable(unsigned BucketNo = 0);
     78 
     79   /// LookupBucketFor - Look up the bucket that the specified string should end
     80   /// up in.  If it already exists as a key in the map, the Item pointer for the
     81   /// specified bucket will be non-null.  Otherwise, it will be null.  In either
     82   /// case, the FullHashValue field of the bucket will be set to the hash value
     83   /// of the string.
     84   unsigned LookupBucketFor(StringRef Key);
     85 
     86   /// FindKey - Look up the bucket that contains the specified key. If it exists
     87   /// in the map, return the bucket number of the key.  Otherwise return -1.
     88   /// This does not modify the map.
     89   int FindKey(StringRef Key) const;
     90 
     91   /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
     92   /// delete it.  This aborts if the value isn't in the table.
     93   void RemoveKey(StringMapEntryBase *V);
     94 
     95   /// RemoveKey - Remove the StringMapEntry for the specified key from the
     96   /// table, returning it.  If the key is not in the table, this returns null.
     97   StringMapEntryBase *RemoveKey(StringRef Key);
     98 
     99   /// Allocate the table with the specified number of buckets and otherwise
    100   /// setup the map as empty.
    101   void init(unsigned Size);
    102 
    103 public:
    104   static StringMapEntryBase *getTombstoneVal() {
    105     uintptr_t Val = static_cast<uintptr_t>(-1);
    106     Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
    107     return reinterpret_cast<StringMapEntryBase *>(Val);
    108   }
    109 
    110   unsigned getNumBuckets() const { return NumBuckets; }
    111   unsigned getNumItems() const { return NumItems; }
    112 
    113   bool empty() const { return NumItems == 0; }
    114   unsigned size() const { return NumItems; }
    115 
    116   void swap(StringMapImpl &Other) {
    117     std::swap(TheTable, Other.TheTable);
    118     std::swap(NumBuckets, Other.NumBuckets);
    119     std::swap(NumItems, Other.NumItems);
    120     std::swap(NumTombstones, Other.NumTombstones);
    121   }
    122 };
    123 
    124 /// StringMapEntry - This is used to represent one value that is inserted into
    125 /// a StringMap.  It contains the Value itself and the key: the string length
    126 /// and data.
    127 template<typename ValueTy>
    128 class StringMapEntry : public StringMapEntryBase {
    129 public:
    130   ValueTy second;
    131 
    132   explicit StringMapEntry(unsigned strLen)
    133     : StringMapEntryBase(strLen), second() {}
    134   template <typename... InitTy>
    135   StringMapEntry(unsigned strLen, InitTy &&... InitVals)
    136       : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
    137   StringMapEntry(StringMapEntry &E) = delete;
    138 
    139   StringRef getKey() const {
    140     return StringRef(getKeyData(), getKeyLength());
    141   }
    142 
    143   const ValueTy &getValue() const { return second; }
    144   ValueTy &getValue() { return second; }
    145 
    146   void setValue(const ValueTy &V) { second = V; }
    147 
    148   /// getKeyData - Return the start of the string data that is the key for this
    149   /// value.  The string data is always stored immediately after the
    150   /// StringMapEntry object.
    151   const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
    152 
    153   StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
    154 
    155   /// Create a StringMapEntry for the specified key construct the value using
    156   /// \p InitiVals.
    157   template <typename AllocatorTy, typename... InitTy>
    158   static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
    159                                 InitTy &&... InitVals) {
    160     unsigned KeyLength = Key.size();
    161 
    162     // Allocate a new item with space for the string at the end and a null
    163     // terminator.
    164     unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
    165       KeyLength+1;
    166     unsigned Alignment = alignof(StringMapEntry);
    167 
    168     StringMapEntry *NewItem =
    169       static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
    170 
    171     // Construct the value.
    172     new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
    173 
    174     // Copy the string information.
    175     char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
    176     if (KeyLength > 0)
    177       memcpy(StrBuffer, Key.data(), KeyLength);
    178     StrBuffer[KeyLength] = 0;  // Null terminate for convenience of clients.
    179     return NewItem;
    180   }
    181 
    182   /// Create - Create a StringMapEntry with normal malloc/free.
    183   template <typename... InitType>
    184   static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
    185     MallocAllocator A;
    186     return Create(Key, A, std::forward<InitType>(InitVal)...);
    187   }
    188 
    189   static StringMapEntry *Create(StringRef Key) {
    190     return Create(Key, ValueTy());
    191   }
    192 
    193   /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
    194   /// into a StringMapEntry, return the StringMapEntry itself.
    195   static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
    196     char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
    197     return *reinterpret_cast<StringMapEntry*>(Ptr);
    198   }
    199 
    200   /// Destroy - Destroy this StringMapEntry, releasing memory back to the
    201   /// specified allocator.
    202   template<typename AllocatorTy>
    203   void Destroy(AllocatorTy &Allocator) {
    204     // Free memory referenced by the item.
    205     unsigned AllocSize =
    206         static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1;
    207     this->~StringMapEntry();
    208     Allocator.Deallocate(static_cast<void *>(this), AllocSize);
    209   }
    210 
    211   /// Destroy this object, releasing memory back to the malloc allocator.
    212   void Destroy() {
    213     MallocAllocator A;
    214     Destroy(A);
    215   }
    216 };
    217 
    218 /// StringMap - This is an unconventional map that is specialized for handling
    219 /// keys that are "strings", which are basically ranges of bytes. This does some
    220 /// funky memory allocation and hashing things to make it extremely efficient,
    221 /// storing the string data *after* the value in the map.
    222 template<typename ValueTy, typename AllocatorTy = MallocAllocator>
    223 class StringMap : public StringMapImpl {
    224   AllocatorTy Allocator;
    225 
    226 public:
    227   typedef StringMapEntry<ValueTy> MapEntryTy;
    228 
    229   StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
    230   explicit StringMap(unsigned InitialSize)
    231     : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
    232 
    233   explicit StringMap(AllocatorTy A)
    234     : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
    235 
    236   StringMap(unsigned InitialSize, AllocatorTy A)
    237     : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
    238       Allocator(A) {}
    239 
    240   StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List)
    241       : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
    242     for (const auto &P : List) {
    243       insert(P);
    244     }
    245   }
    246 
    247   StringMap(StringMap &&RHS)
    248       : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
    249 
    250   StringMap &operator=(StringMap RHS) {
    251     StringMapImpl::swap(RHS);
    252     std::swap(Allocator, RHS.Allocator);
    253     return *this;
    254   }
    255 
    256   StringMap(const StringMap &RHS) :
    257     StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
    258     Allocator(RHS.Allocator) {
    259     if (RHS.empty())
    260       return;
    261 
    262     // Allocate TheTable of the same size as RHS's TheTable, and set the
    263     // sentinel appropriately (and NumBuckets).
    264     init(RHS.NumBuckets);
    265     unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1),
    266              *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1);
    267 
    268     NumItems = RHS.NumItems;
    269     NumTombstones = RHS.NumTombstones;
    270     for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
    271       StringMapEntryBase *Bucket = RHS.TheTable[I];
    272       if (!Bucket || Bucket == getTombstoneVal()) {
    273         TheTable[I] = Bucket;
    274         continue;
    275       }
    276 
    277       TheTable[I] = MapEntryTy::Create(
    278           static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
    279           static_cast<MapEntryTy *>(Bucket)->getValue());
    280       HashTable[I] = RHSHashTable[I];
    281     }
    282 
    283     // Note that here we've copied everything from the RHS into this object,
    284     // tombstones included. We could, instead, have re-probed for each key to
    285     // instantiate this new object without any tombstone buckets. The
    286     // assumption here is that items are rarely deleted from most StringMaps,
    287     // and so tombstones are rare, so the cost of re-probing for all inputs is
    288     // not worthwhile.
    289   }
    290 
    291   AllocatorTy &getAllocator() { return Allocator; }
    292   const AllocatorTy &getAllocator() const { return Allocator; }
    293 
    294   typedef const char* key_type;
    295   typedef ValueTy mapped_type;
    296   typedef StringMapEntry<ValueTy> value_type;
    297   typedef size_t size_type;
    298 
    299   typedef StringMapConstIterator<ValueTy> const_iterator;
    300   typedef StringMapIterator<ValueTy> iterator;
    301 
    302   iterator begin() {
    303     return iterator(TheTable, NumBuckets == 0);
    304   }
    305   iterator end() {
    306     return iterator(TheTable+NumBuckets, true);
    307   }
    308   const_iterator begin() const {
    309     return const_iterator(TheTable, NumBuckets == 0);
    310   }
    311   const_iterator end() const {
    312     return const_iterator(TheTable+NumBuckets, true);
    313   }
    314 
    315   iterator find(StringRef Key) {
    316     int Bucket = FindKey(Key);
    317     if (Bucket == -1) return end();
    318     return iterator(TheTable+Bucket, true);
    319   }
    320 
    321   const_iterator find(StringRef Key) const {
    322     int Bucket = FindKey(Key);
    323     if (Bucket == -1) return end();
    324     return const_iterator(TheTable+Bucket, true);
    325   }
    326 
    327   /// lookup - Return the entry for the specified key, or a default
    328   /// constructed value if no such entry exists.
    329   ValueTy lookup(StringRef Key) const {
    330     const_iterator it = find(Key);
    331     if (it != end())
    332       return it->second;
    333     return ValueTy();
    334   }
    335 
    336   /// Lookup the ValueTy for the \p Key, or create a default constructed value
    337   /// if the key is not in the map.
    338   ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; }
    339 
    340   /// count - Return 1 if the element is in the map, 0 otherwise.
    341   size_type count(StringRef Key) const {
    342     return find(Key) == end() ? 0 : 1;
    343   }
    344 
    345   /// insert - Insert the specified key/value pair into the map.  If the key
    346   /// already exists in the map, return false and ignore the request, otherwise
    347   /// insert it and return true.
    348   bool insert(MapEntryTy *KeyValue) {
    349     unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
    350     StringMapEntryBase *&Bucket = TheTable[BucketNo];
    351     if (Bucket && Bucket != getTombstoneVal())
    352       return false;  // Already exists in map.
    353 
    354     if (Bucket == getTombstoneVal())
    355       --NumTombstones;
    356     Bucket = KeyValue;
    357     ++NumItems;
    358     assert(NumItems + NumTombstones <= NumBuckets);
    359 
    360     RehashTable();
    361     return true;
    362   }
    363 
    364   /// insert - Inserts the specified key/value pair into the map if the key
    365   /// isn't already in the map. The bool component of the returned pair is true
    366   /// if and only if the insertion takes place, and the iterator component of
    367   /// the pair points to the element with key equivalent to the key of the pair.
    368   std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
    369     return try_emplace(KV.first, std::move(KV.second));
    370   }
    371 
    372   /// Emplace a new element for the specified key into the map if the key isn't
    373   /// already in the map. The bool component of the returned pair is true
    374   /// if and only if the insertion takes place, and the iterator component of
    375   /// the pair points to the element with key equivalent to the key of the pair.
    376   template <typename... ArgsTy>
    377   std::pair<iterator, bool> try_emplace(StringRef Key, ArgsTy &&... Args) {
    378     unsigned BucketNo = LookupBucketFor(Key);
    379     StringMapEntryBase *&Bucket = TheTable[BucketNo];
    380     if (Bucket && Bucket != getTombstoneVal())
    381       return std::make_pair(iterator(TheTable + BucketNo, false),
    382                             false); // Already exists in map.
    383 
    384     if (Bucket == getTombstoneVal())
    385       --NumTombstones;
    386     Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
    387     ++NumItems;
    388     assert(NumItems + NumTombstones <= NumBuckets);
    389 
    390     BucketNo = RehashTable(BucketNo);
    391     return std::make_pair(iterator(TheTable + BucketNo, false), true);
    392   }
    393 
    394   // clear - Empties out the StringMap
    395   void clear() {
    396     if (empty()) return;
    397 
    398     // Zap all values, resetting the keys back to non-present (not tombstone),
    399     // which is safe because we're removing all elements.
    400     for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
    401       StringMapEntryBase *&Bucket = TheTable[I];
    402       if (Bucket && Bucket != getTombstoneVal()) {
    403         static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
    404       }
    405       Bucket = nullptr;
    406     }
    407 
    408     NumItems = 0;
    409     NumTombstones = 0;
    410   }
    411 
    412   /// remove - Remove the specified key/value pair from the map, but do not
    413   /// erase it.  This aborts if the key is not in the map.
    414   void remove(MapEntryTy *KeyValue) {
    415     RemoveKey(KeyValue);
    416   }
    417 
    418   void erase(iterator I) {
    419     MapEntryTy &V = *I;
    420     remove(&V);
    421     V.Destroy(Allocator);
    422   }
    423 
    424   bool erase(StringRef Key) {
    425     iterator I = find(Key);
    426     if (I == end()) return false;
    427     erase(I);
    428     return true;
    429   }
    430 
    431   ~StringMap() {
    432     // Delete all the elements in the map, but don't reset the elements
    433     // to default values.  This is a copy of clear(), but avoids unnecessary
    434     // work not required in the destructor.
    435     if (!empty()) {
    436       for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
    437         StringMapEntryBase *Bucket = TheTable[I];
    438         if (Bucket && Bucket != getTombstoneVal()) {
    439           static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
    440         }
    441       }
    442     }
    443     free(TheTable);
    444   }
    445 };
    446 
    447 template <typename ValueTy> class StringMapConstIterator {
    448 protected:
    449   StringMapEntryBase **Ptr = nullptr;
    450 
    451 public:
    452   typedef StringMapEntry<ValueTy> value_type;
    453 
    454   StringMapConstIterator() = default;
    455 
    456   explicit StringMapConstIterator(StringMapEntryBase **Bucket,
    457                                   bool NoAdvance = false)
    458   : Ptr(Bucket) {
    459     if (!NoAdvance) AdvancePastEmptyBuckets();
    460   }
    461 
    462   const value_type &operator*() const {
    463     return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
    464   }
    465   const value_type *operator->() const {
    466     return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
    467   }
    468 
    469   bool operator==(const StringMapConstIterator &RHS) const {
    470     return Ptr == RHS.Ptr;
    471   }
    472   bool operator!=(const StringMapConstIterator &RHS) const {
    473     return Ptr != RHS.Ptr;
    474   }
    475 
    476   inline StringMapConstIterator& operator++() {   // Preincrement
    477     ++Ptr;
    478     AdvancePastEmptyBuckets();
    479     return *this;
    480   }
    481   StringMapConstIterator operator++(int) {        // Postincrement
    482     StringMapConstIterator tmp = *this; ++*this; return tmp;
    483   }
    484 
    485 private:
    486   void AdvancePastEmptyBuckets() {
    487     while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
    488       ++Ptr;
    489   }
    490 };
    491 
    492 template<typename ValueTy>
    493 class StringMapIterator : public StringMapConstIterator<ValueTy> {
    494 public:
    495   StringMapIterator() = default;
    496 
    497   explicit StringMapIterator(StringMapEntryBase **Bucket,
    498                              bool NoAdvance = false)
    499     : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
    500   }
    501 
    502   StringMapEntry<ValueTy> &operator*() const {
    503     return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
    504   }
    505   StringMapEntry<ValueTy> *operator->() const {
    506     return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
    507   }
    508 };
    509 
    510 } // end namespace llvm
    511 
    512 #endif // LLVM_ADT_STRINGMAP_H
    513