• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
StringMapEntryBase(unsigned Len)43   explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
44 
getKeyLength()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:
StringMapImpl(unsigned itemSize)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) {}
StringMapImpl(StringMapImpl && RHS)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:
getTombstoneVal()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 
getNumBuckets()110   unsigned getNumBuckets() const { return NumBuckets; }
getNumItems()111   unsigned getNumItems() const { return NumItems; }
112 
empty()113   bool empty() const { return NumItems == 0; }
size()114   unsigned size() const { return NumItems; }
115 
swap(StringMapImpl & Other)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 
StringMapEntry(unsigned strLen)132   explicit StringMapEntry(unsigned strLen)
133     : StringMapEntryBase(strLen), second() {}
134   template <typename... InitTy>
StringMapEntry(unsigned strLen,InitTy &&...InitVals)135   StringMapEntry(unsigned strLen, InitTy &&... InitVals)
136       : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
137   StringMapEntry(StringMapEntry &E) = delete;
138 
getKey()139   StringRef getKey() const {
140     return StringRef(getKeyData(), getKeyLength());
141   }
142 
getValue()143   const ValueTy &getValue() const { return second; }
getValue()144   ValueTy &getValue() { return second; }
145 
setValue(const ValueTy & V)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.
getKeyData()151   const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
152 
first()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>
Create(StringRef Key,AllocatorTy & Allocator,InitTy &&...InitVals)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>
Create(StringRef Key,InitType &&...InitVal)184   static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
185     MallocAllocator A;
186     return Create(Key, A, std::forward<InitType>(InitVal)...);
187   }
188 
Create(StringRef Key)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.
GetStringMapEntryFromKeyData(const char * KeyData)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>
Destroy(AllocatorTy & Allocator)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.
Destroy()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 
StringMap()229   StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
StringMap(unsigned InitialSize)230   explicit StringMap(unsigned InitialSize)
231     : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
232 
StringMap(AllocatorTy A)233   explicit StringMap(AllocatorTy A)
234     : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
235 
StringMap(unsigned InitialSize,AllocatorTy A)236   StringMap(unsigned InitialSize, AllocatorTy A)
237     : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
238       Allocator(A) {}
239 
StringMap(std::initializer_list<std::pair<StringRef,ValueTy>> List)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 
StringMap(StringMap && RHS)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 
StringMap(const StringMap & RHS)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 
getAllocator()291   AllocatorTy &getAllocator() { return Allocator; }
getAllocator()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 
begin()302   iterator begin() {
303     return iterator(TheTable, NumBuckets == 0);
304   }
end()305   iterator end() {
306     return iterator(TheTable+NumBuckets, true);
307   }
begin()308   const_iterator begin() const {
309     return const_iterator(TheTable, NumBuckets == 0);
310   }
end()311   const_iterator end() const {
312     return const_iterator(TheTable+NumBuckets, true);
313   }
314 
find(StringRef Key)315   iterator find(StringRef Key) {
316     int Bucket = FindKey(Key);
317     if (Bucket == -1) return end();
318     return iterator(TheTable+Bucket, true);
319   }
320 
find(StringRef Key)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.
lookup(StringRef Key)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.
count(StringRef Key)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.
insert(MapEntryTy * KeyValue)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.
insert(std::pair<StringRef,ValueTy> KV)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>
try_emplace(StringRef Key,ArgsTy &&...Args)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
clear()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.
remove(MapEntryTy * KeyValue)414   void remove(MapEntryTy *KeyValue) {
415     RemoveKey(KeyValue);
416   }
417 
erase(iterator I)418   void erase(iterator I) {
419     MapEntryTy &V = *I;
420     remove(&V);
421     V.Destroy(Allocator);
422   }
423 
erase(StringRef Key)424   bool erase(StringRef Key) {
425     iterator I = find(Key);
426     if (I == end()) return false;
427     erase(I);
428     return true;
429   }
430 
~StringMap()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)
Ptr(Bucket)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:
AdvancePastEmptyBuckets()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