StringMap.h 16 KB

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