StringMap.h 17 KB

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