Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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