1 //===- StringMap.h - String Hash table map interface ------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the StringMap class.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_ADT_STRINGMAP_H
14 #define LLVM_ADT_STRINGMAP_H
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/iterator.h"
18 #include "llvm/ADT/iterator_range.h"
19 #include "llvm/Support/Allocator.h"
20 #include "llvm/Support/PointerLikeTypeTraits.h"
21 #include "llvm/Support/ErrorHandling.h"
27 #include <initializer_list>
33 template<typename ValueTy
> class StringMapConstIterator
;
34 template<typename ValueTy
> class StringMapIterator
;
35 template<typename ValueTy
> class StringMapKeyIterator
;
37 /// StringMapEntryBase - Shared base class of StringMapEntry instances.
38 class StringMapEntryBase
{
42 explicit StringMapEntryBase(size_t Len
) : StrLen(Len
) {}
44 size_t getKeyLength() const { return StrLen
; }
47 /// StringMapImpl - This is the base class of StringMap that is shared among
48 /// all of its instantiations.
51 // Array of NumBuckets pointers to entries, null pointers are holes.
52 // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
53 // by an array of the actual hash values as unsigned integers.
54 StringMapEntryBase
**TheTable
= nullptr;
55 unsigned NumBuckets
= 0;
56 unsigned NumItems
= 0;
57 unsigned NumTombstones
= 0;
61 explicit StringMapImpl(unsigned itemSize
)
62 : ItemSize(itemSize
) {}
63 StringMapImpl(StringMapImpl
&&RHS
)
64 : TheTable(RHS
.TheTable
), NumBuckets(RHS
.NumBuckets
),
65 NumItems(RHS
.NumItems
), NumTombstones(RHS
.NumTombstones
),
66 ItemSize(RHS
.ItemSize
) {
67 RHS
.TheTable
= nullptr;
70 RHS
.NumTombstones
= 0;
73 StringMapImpl(unsigned InitSize
, unsigned ItemSize
);
74 unsigned RehashTable(unsigned BucketNo
= 0);
76 /// LookupBucketFor - Look up the bucket that the specified string should end
77 /// up in. If it already exists as a key in the map, the Item pointer for the
78 /// specified bucket will be non-null. Otherwise, it will be null. In either
79 /// case, the FullHashValue field of the bucket will be set to the hash value
81 unsigned LookupBucketFor(StringRef Key
);
83 /// FindKey - Look up the bucket that contains the specified key. If it exists
84 /// in the map, return the bucket number of the key. Otherwise return -1.
85 /// This does not modify the map.
86 int FindKey(StringRef Key
) const;
88 /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
89 /// delete it. This aborts if the value isn't in the table.
90 void RemoveKey(StringMapEntryBase
*V
);
92 /// RemoveKey - Remove the StringMapEntry for the specified key from the
93 /// table, returning it. If the key is not in the table, this returns null.
94 StringMapEntryBase
*RemoveKey(StringRef Key
);
96 /// Allocate the table with the specified number of buckets and otherwise
97 /// setup the map as empty.
98 void init(unsigned Size
);
101 static StringMapEntryBase
*getTombstoneVal() {
102 uintptr_t Val
= static_cast<uintptr_t>(-1);
103 Val
<<= PointerLikeTypeTraits
<StringMapEntryBase
*>::NumLowBitsAvailable
;
104 return reinterpret_cast<StringMapEntryBase
*>(Val
);
107 unsigned getNumBuckets() const { return NumBuckets
; }
108 unsigned getNumItems() const { return NumItems
; }
110 bool empty() const { return NumItems
== 0; }
111 unsigned size() const { return NumItems
; }
113 void swap(StringMapImpl
&Other
) {
114 std::swap(TheTable
, Other
.TheTable
);
115 std::swap(NumBuckets
, Other
.NumBuckets
);
116 std::swap(NumItems
, Other
.NumItems
);
117 std::swap(NumTombstones
, Other
.NumTombstones
);
121 /// StringMapEntryStorage - Holds the value in a StringMapEntry.
123 /// Factored out into a separate base class to make it easier to specialize.
124 /// This is primarily intended to support StringSet, which doesn't need a value
126 template<typename ValueTy
>
127 class StringMapEntryStorage
: public StringMapEntryBase
{
131 explicit StringMapEntryStorage(size_t strLen
)
132 : StringMapEntryBase(strLen
), second() {}
133 template <typename
... InitTy
>
134 StringMapEntryStorage(size_t strLen
, InitTy
&&... InitVals
)
135 : StringMapEntryBase(strLen
), second(std::forward
<InitTy
>(InitVals
)...) {}
136 StringMapEntryStorage(StringMapEntryStorage
&E
) = delete;
138 const ValueTy
&getValue() const { return second
; }
139 ValueTy
&getValue() { return second
; }
141 void setValue(const ValueTy
&V
) { second
= V
; }
145 class StringMapEntryStorage
<NoneType
> : public StringMapEntryBase
{
147 explicit StringMapEntryStorage(size_t strLen
, NoneType none
= None
)
148 : StringMapEntryBase(strLen
) {}
149 StringMapEntryStorage(StringMapEntryStorage
&E
) = delete;
151 NoneType
getValue() const { return None
; }
154 /// StringMapEntry - This is used to represent one value that is inserted into
155 /// a StringMap. It contains the Value itself and the key: the string length
157 template<typename ValueTy
>
158 class StringMapEntry final
: public StringMapEntryStorage
<ValueTy
> {
160 using StringMapEntryStorage
<ValueTy
>::StringMapEntryStorage
;
162 StringRef
getKey() const {
163 return StringRef(getKeyData(), this->getKeyLength());
166 /// getKeyData - Return the start of the string data that is the key for this
167 /// value. The string data is always stored immediately after the
168 /// StringMapEntry object.
169 const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
171 StringRef
first() const {
172 return StringRef(getKeyData(), this->getKeyLength());
175 /// Create a StringMapEntry for the specified key construct the value using
177 template <typename AllocatorTy
, typename
... InitTy
>
178 static StringMapEntry
*Create(StringRef Key
, AllocatorTy
&Allocator
,
179 InitTy
&&... InitVals
) {
180 size_t KeyLength
= Key
.size();
182 // Allocate a new item with space for the string at the end and a null
184 size_t AllocSize
= sizeof(StringMapEntry
) + KeyLength
+ 1;
185 size_t Alignment
= alignof(StringMapEntry
);
187 StringMapEntry
*NewItem
=
188 static_cast<StringMapEntry
*>(Allocator
.Allocate(AllocSize
,Alignment
));
189 assert(NewItem
&& "Unhandled out-of-memory");
191 // Construct the value.
192 new (NewItem
) StringMapEntry(KeyLength
, std::forward
<InitTy
>(InitVals
)...);
194 // Copy the string information.
195 char *StrBuffer
= const_cast<char*>(NewItem
->getKeyData());
197 memcpy(StrBuffer
, Key
.data(), KeyLength
);
198 StrBuffer
[KeyLength
] = 0; // Null terminate for convenience of clients.
202 /// Create - Create a StringMapEntry with normal malloc/free.
203 template <typename
... InitType
>
204 static StringMapEntry
*Create(StringRef Key
, InitType
&&... InitVal
) {
206 return Create(Key
, A
, std::forward
<InitType
>(InitVal
)...);
209 static StringMapEntry
*Create(StringRef Key
) {
210 return Create(Key
, ValueTy());
213 /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
214 /// into a StringMapEntry, return the StringMapEntry itself.
215 static StringMapEntry
&GetStringMapEntryFromKeyData(const char *KeyData
) {
216 char *Ptr
= const_cast<char*>(KeyData
) - sizeof(StringMapEntry
<ValueTy
>);
217 return *reinterpret_cast<StringMapEntry
*>(Ptr
);
220 /// Destroy - Destroy this StringMapEntry, releasing memory back to the
221 /// specified allocator.
222 template<typename AllocatorTy
>
223 void Destroy(AllocatorTy
&Allocator
) {
224 // Free memory referenced by the item.
225 size_t AllocSize
= sizeof(StringMapEntry
) + this->getKeyLength() + 1;
226 this->~StringMapEntry();
227 Allocator
.Deallocate(static_cast<void *>(this), AllocSize
);
230 /// Destroy this object, releasing memory back to the malloc allocator.
237 /// StringMap - This is an unconventional map that is specialized for handling
238 /// keys that are "strings", which are basically ranges of bytes. This does some
239 /// funky memory allocation and hashing things to make it extremely efficient,
240 /// storing the string data *after* the value in the map.
241 template<typename ValueTy
, typename AllocatorTy
= MallocAllocator
>
242 class StringMap
: public StringMapImpl
{
243 AllocatorTy Allocator
;
246 using MapEntryTy
= StringMapEntry
<ValueTy
>;
248 StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy
))) {}
250 explicit StringMap(unsigned InitialSize
)
251 : StringMapImpl(InitialSize
, static_cast<unsigned>(sizeof(MapEntryTy
))) {}
253 explicit StringMap(AllocatorTy A
)
254 : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy
))), Allocator(A
) {}
256 StringMap(unsigned InitialSize
, AllocatorTy A
)
257 : StringMapImpl(InitialSize
, static_cast<unsigned>(sizeof(MapEntryTy
))),
260 StringMap(std::initializer_list
<std::pair
<StringRef
, ValueTy
>> List
)
261 : StringMapImpl(List
.size(), static_cast<unsigned>(sizeof(MapEntryTy
))) {
262 for (const auto &P
: List
) {
267 StringMap(StringMap
&&RHS
)
268 : StringMapImpl(std::move(RHS
)), Allocator(std::move(RHS
.Allocator
)) {}
270 StringMap(const StringMap
&RHS
) :
271 StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy
))),
272 Allocator(RHS
.Allocator
) {
276 // Allocate TheTable of the same size as RHS's TheTable, and set the
277 // sentinel appropriately (and NumBuckets).
278 init(RHS
.NumBuckets
);
279 unsigned *HashTable
= (unsigned *)(TheTable
+ NumBuckets
+ 1),
280 *RHSHashTable
= (unsigned *)(RHS
.TheTable
+ NumBuckets
+ 1);
282 NumItems
= RHS
.NumItems
;
283 NumTombstones
= RHS
.NumTombstones
;
284 for (unsigned I
= 0, E
= NumBuckets
; I
!= E
; ++I
) {
285 StringMapEntryBase
*Bucket
= RHS
.TheTable
[I
];
286 if (!Bucket
|| Bucket
== getTombstoneVal()) {
287 TheTable
[I
] = Bucket
;
291 TheTable
[I
] = MapEntryTy::Create(
292 static_cast<MapEntryTy
*>(Bucket
)->getKey(), Allocator
,
293 static_cast<MapEntryTy
*>(Bucket
)->getValue());
294 HashTable
[I
] = RHSHashTable
[I
];
297 // Note that here we've copied everything from the RHS into this object,
298 // tombstones included. We could, instead, have re-probed for each key to
299 // instantiate this new object without any tombstone buckets. The
300 // assumption here is that items are rarely deleted from most StringMaps,
301 // and so tombstones are rare, so the cost of re-probing for all inputs is
305 StringMap
&operator=(StringMap RHS
) {
306 StringMapImpl::swap(RHS
);
307 std::swap(Allocator
, RHS
.Allocator
);
312 // Delete all the elements in the map, but don't reset the elements
313 // to default values. This is a copy of clear(), but avoids unnecessary
314 // work not required in the destructor.
316 for (unsigned I
= 0, E
= NumBuckets
; I
!= E
; ++I
) {
317 StringMapEntryBase
*Bucket
= TheTable
[I
];
318 if (Bucket
&& Bucket
!= getTombstoneVal()) {
319 static_cast<MapEntryTy
*>(Bucket
)->Destroy(Allocator
);
326 AllocatorTy
&getAllocator() { return Allocator
; }
327 const AllocatorTy
&getAllocator() const { return Allocator
; }
329 using key_type
= const char*;
330 using mapped_type
= ValueTy
;
331 using value_type
= StringMapEntry
<ValueTy
>;
332 using size_type
= size_t;
334 using const_iterator
= StringMapConstIterator
<ValueTy
>;
335 using iterator
= StringMapIterator
<ValueTy
>;
338 return iterator(TheTable
, NumBuckets
== 0);
341 return iterator(TheTable
+NumBuckets
, true);
343 const_iterator
begin() const {
344 return const_iterator(TheTable
, NumBuckets
== 0);
346 const_iterator
end() const {
347 return const_iterator(TheTable
+NumBuckets
, true);
350 iterator_range
<StringMapKeyIterator
<ValueTy
>> keys() const {
351 return make_range(StringMapKeyIterator
<ValueTy
>(begin()),
352 StringMapKeyIterator
<ValueTy
>(end()));
355 iterator
find(StringRef Key
) {
356 int Bucket
= FindKey(Key
);
357 if (Bucket
== -1) return end();
358 return iterator(TheTable
+Bucket
, true);
361 const_iterator
find(StringRef Key
) const {
362 int Bucket
= FindKey(Key
);
363 if (Bucket
== -1) return end();
364 return const_iterator(TheTable
+Bucket
, true);
367 /// lookup - Return the entry for the specified key, or a default
368 /// constructed value if no such entry exists.
369 ValueTy
lookup(StringRef Key
) const {
370 const_iterator it
= find(Key
);
376 /// Lookup the ValueTy for the \p Key, or create a default constructed value
377 /// if the key is not in the map.
378 ValueTy
&operator[](StringRef Key
) { return try_emplace(Key
).first
->second
; }
380 /// count - Return 1 if the element is in the map, 0 otherwise.
381 size_type
count(StringRef Key
) const {
382 return find(Key
) == end() ? 0 : 1;
385 template <typename InputTy
>
386 size_type
count(const StringMapEntry
<InputTy
> &MapEntry
) const {
387 return count(MapEntry
.getKey());
390 /// insert - Insert the specified key/value pair into the map. If the key
391 /// already exists in the map, return false and ignore the request, otherwise
392 /// insert it and return true.
393 bool insert(MapEntryTy
*KeyValue
) {
394 unsigned BucketNo
= LookupBucketFor(KeyValue
->getKey());
395 StringMapEntryBase
*&Bucket
= TheTable
[BucketNo
];
396 if (Bucket
&& Bucket
!= getTombstoneVal())
397 return false; // Already exists in map.
399 if (Bucket
== getTombstoneVal())
403 assert(NumItems
+ NumTombstones
<= NumBuckets
);
409 /// insert - Inserts the specified key/value pair into the map if the key
410 /// isn't already in the map. The bool component of the returned pair is true
411 /// if and only if the insertion takes place, and the iterator component of
412 /// the pair points to the element with key equivalent to the key of the pair.
413 std::pair
<iterator
, bool> insert(std::pair
<StringRef
, ValueTy
> KV
) {
414 return try_emplace(KV
.first
, std::move(KV
.second
));
417 /// Inserts an element or assigns to the current element if the key already
418 /// exists. The return type is the same as try_emplace.
419 template <typename V
>
420 std::pair
<iterator
, bool> insert_or_assign(StringRef Key
, V
&&Val
) {
421 auto Ret
= try_emplace(Key
, std::forward
<V
>(Val
));
423 Ret
.first
->second
= std::forward
<V
>(Val
);
427 /// Emplace a new element for the specified key into the map if the key isn't
428 /// already in the map. The bool component of the returned pair is true
429 /// if and only if the insertion takes place, and the iterator component of
430 /// the pair points to the element with key equivalent to the key of the pair.
431 template <typename
... ArgsTy
>
432 std::pair
<iterator
, bool> try_emplace(StringRef Key
, ArgsTy
&&... Args
) {
433 unsigned BucketNo
= LookupBucketFor(Key
);
434 StringMapEntryBase
*&Bucket
= TheTable
[BucketNo
];
435 if (Bucket
&& Bucket
!= getTombstoneVal())
436 return std::make_pair(iterator(TheTable
+ BucketNo
, false),
437 false); // Already exists in map.
439 if (Bucket
== getTombstoneVal())
441 Bucket
= MapEntryTy::Create(Key
, Allocator
, std::forward
<ArgsTy
>(Args
)...);
443 assert(NumItems
+ NumTombstones
<= NumBuckets
);
445 BucketNo
= RehashTable(BucketNo
);
446 return std::make_pair(iterator(TheTable
+ BucketNo
, false), true);
449 // clear - Empties out the StringMap
453 // Zap all values, resetting the keys back to non-present (not tombstone),
454 // which is safe because we're removing all elements.
455 for (unsigned I
= 0, E
= NumBuckets
; I
!= E
; ++I
) {
456 StringMapEntryBase
*&Bucket
= TheTable
[I
];
457 if (Bucket
&& Bucket
!= getTombstoneVal()) {
458 static_cast<MapEntryTy
*>(Bucket
)->Destroy(Allocator
);
467 /// remove - Remove the specified key/value pair from the map, but do not
468 /// erase it. This aborts if the key is not in the map.
469 void remove(MapEntryTy
*KeyValue
) {
473 void erase(iterator I
) {
476 V
.Destroy(Allocator
);
479 bool erase(StringRef Key
) {
480 iterator I
= find(Key
);
481 if (I
== end()) return false;
487 template <typename DerivedTy
, typename ValueTy
>
488 class StringMapIterBase
489 : public iterator_facade_base
<DerivedTy
, std::forward_iterator_tag
,
492 StringMapEntryBase
**Ptr
= nullptr;
495 StringMapIterBase() = default;
497 explicit StringMapIterBase(StringMapEntryBase
**Bucket
,
498 bool NoAdvance
= false)
500 if (!NoAdvance
) AdvancePastEmptyBuckets();
503 DerivedTy
&operator=(const DerivedTy
&Other
) {
505 return static_cast<DerivedTy
&>(*this);
508 bool operator==(const DerivedTy
&RHS
) const { return Ptr
== RHS
.Ptr
; }
510 DerivedTy
&operator++() { // Preincrement
512 AdvancePastEmptyBuckets();
513 return static_cast<DerivedTy
&>(*this);
516 DerivedTy
operator++(int) { // Post-increment
523 void AdvancePastEmptyBuckets() {
524 while (*Ptr
== nullptr || *Ptr
== StringMapImpl::getTombstoneVal())
529 template <typename ValueTy
>
530 class StringMapConstIterator
531 : public StringMapIterBase
<StringMapConstIterator
<ValueTy
>,
532 const StringMapEntry
<ValueTy
>> {
533 using base
= StringMapIterBase
<StringMapConstIterator
<ValueTy
>,
534 const StringMapEntry
<ValueTy
>>;
537 StringMapConstIterator() = default;
538 explicit StringMapConstIterator(StringMapEntryBase
**Bucket
,
539 bool NoAdvance
= false)
540 : base(Bucket
, NoAdvance
) {}
542 const StringMapEntry
<ValueTy
> &operator*() const {
543 return *static_cast<const StringMapEntry
<ValueTy
> *>(*this->Ptr
);
547 template <typename ValueTy
>
548 class StringMapIterator
: public StringMapIterBase
<StringMapIterator
<ValueTy
>,
549 StringMapEntry
<ValueTy
>> {
551 StringMapIterBase
<StringMapIterator
<ValueTy
>, StringMapEntry
<ValueTy
>>;
554 StringMapIterator() = default;
555 explicit StringMapIterator(StringMapEntryBase
**Bucket
,
556 bool NoAdvance
= false)
557 : base(Bucket
, NoAdvance
) {}
559 StringMapEntry
<ValueTy
> &operator*() const {
560 return *static_cast<StringMapEntry
<ValueTy
> *>(*this->Ptr
);
563 operator StringMapConstIterator
<ValueTy
>() const {
564 return StringMapConstIterator
<ValueTy
>(this->Ptr
, true);
568 template <typename ValueTy
>
569 class StringMapKeyIterator
570 : public iterator_adaptor_base
<StringMapKeyIterator
<ValueTy
>,
571 StringMapConstIterator
<ValueTy
>,
572 std::forward_iterator_tag
, StringRef
> {
573 using base
= iterator_adaptor_base
<StringMapKeyIterator
<ValueTy
>,
574 StringMapConstIterator
<ValueTy
>,
575 std::forward_iterator_tag
, StringRef
>;
578 StringMapKeyIterator() = default;
579 explicit StringMapKeyIterator(StringMapConstIterator
<ValueTy
> Iter
)
580 : base(std::move(Iter
)) {}
582 StringRef
&operator*() {
583 Key
= this->wrapped()->getKey();
591 } // end namespace llvm
593 #endif // LLVM_ADT_STRINGMAP_H