StringMap.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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. #ifndef LLVM_ADT_STRINGMAP_H
  14. #define LLVM_ADT_STRINGMAP_H
  15. #include "llvm/ADT/StringRef.h"
  16. #include "llvm/Support/Allocator.h"
  17. #include <cstring>
  18. #include <utility>
  19. namespace llvm {
  20. template<typename ValueT>
  21. class StringMapConstIterator;
  22. template<typename ValueT>
  23. class StringMapIterator;
  24. template<typename ValueTy>
  25. class StringMapEntry;
  26. /// StringMapEntryBase - Shared base class of StringMapEntry instances.
  27. class StringMapEntryBase {
  28. unsigned StrLen;
  29. public:
  30. explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
  31. unsigned getKeyLength() const { return StrLen; }
  32. };
  33. /// StringMapImpl - This is the base class of StringMap that is shared among
  34. /// all of its instantiations.
  35. class StringMapImpl {
  36. protected:
  37. // Array of NumBuckets pointers to entries, null pointers are holes.
  38. // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
  39. // by an array of the actual hash values as unsigned integers.
  40. StringMapEntryBase **TheTable;
  41. unsigned NumBuckets;
  42. unsigned NumItems;
  43. unsigned NumTombstones;
  44. unsigned ItemSize;
  45. protected:
  46. explicit StringMapImpl(unsigned itemSize)
  47. : TheTable(nullptr),
  48. // Initialize the map with zero buckets to allocation.
  49. NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {}
  50. StringMapImpl(StringMapImpl &&RHS)
  51. : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
  52. NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
  53. ItemSize(RHS.ItemSize) {
  54. RHS.TheTable = nullptr;
  55. RHS.NumBuckets = 0;
  56. RHS.NumItems = 0;
  57. RHS.NumTombstones = 0;
  58. }
  59. StringMapImpl(unsigned InitSize, unsigned ItemSize);
  60. unsigned RehashTable(unsigned BucketNo = 0);
  61. /// LookupBucketFor - Look up the bucket that the specified string should end
  62. /// up in. If it already exists as a key in the map, the Item pointer for the
  63. /// specified bucket will be non-null. Otherwise, it will be null. In either
  64. /// case, the FullHashValue field of the bucket will be set to the hash value
  65. /// of the string.
  66. unsigned LookupBucketFor(StringRef Key);
  67. /// FindKey - Look up the bucket that contains the specified key. If it exists
  68. /// in the map, return the bucket number of the key. Otherwise return -1.
  69. /// This does not modify the map.
  70. int FindKey(StringRef Key) const;
  71. /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
  72. /// delete it. This aborts if the value isn't in the table.
  73. void RemoveKey(StringMapEntryBase *V);
  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. private:
  78. void init(unsigned Size);
  79. public:
  80. static StringMapEntryBase *getTombstoneVal() {
  81. return (StringMapEntryBase*)-1;
  82. }
  83. unsigned getNumBuckets() const { return NumBuckets; }
  84. unsigned getNumItems() const { return NumItems; }
  85. bool empty() const { return NumItems == 0; }
  86. unsigned size() const { return NumItems; }
  87. void swap(StringMapImpl &Other) {
  88. std::swap(TheTable, Other.TheTable);
  89. std::swap(NumBuckets, Other.NumBuckets);
  90. std::swap(NumItems, Other.NumItems);
  91. std::swap(NumTombstones, Other.NumTombstones);
  92. }
  93. };
  94. /// StringMapEntry - This is used to represent one value that is inserted into
  95. /// a StringMap. It contains the Value itself and the key: the string length
  96. /// and data.
  97. template<typename ValueTy>
  98. class StringMapEntry : public StringMapEntryBase {
  99. StringMapEntry(StringMapEntry &E) = delete;
  100. public:
  101. ValueTy second;
  102. explicit StringMapEntry(unsigned strLen)
  103. : StringMapEntryBase(strLen), second() {}
  104. template <class InitTy>
  105. StringMapEntry(unsigned strLen, InitTy &&V)
  106. : StringMapEntryBase(strLen), second(std::forward<InitTy>(V)) {}
  107. StringRef getKey() const {
  108. return StringRef(getKeyData(), getKeyLength());
  109. }
  110. const ValueTy &getValue() const { return second; }
  111. ValueTy &getValue() { return second; }
  112. void setValue(const ValueTy &V) { second = V; }
  113. /// getKeyData - Return the start of the string data that is the key for this
  114. /// value. The string data is always stored immediately after the
  115. /// StringMapEntry object.
  116. const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
  117. StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
  118. /// Create - Create a StringMapEntry for the specified key and default
  119. /// construct the value.
  120. template <typename AllocatorTy, typename InitType>
  121. static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
  122. InitType &&InitVal) {
  123. unsigned KeyLength = Key.size();
  124. // Allocate a new item with space for the string at the end and a null
  125. // terminator.
  126. unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
  127. KeyLength+1;
  128. unsigned Alignment = alignOf<StringMapEntry>();
  129. StringMapEntry *NewItem =
  130. static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
  131. // Default construct the value.
  132. new (NewItem) StringMapEntry(KeyLength, std::forward<InitType>(InitVal));
  133. // Copy the string information.
  134. char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
  135. if (KeyLength > 0)
  136. memcpy(StrBuffer, Key.data(), KeyLength);
  137. StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients.
  138. return NewItem;
  139. }
  140. template<typename AllocatorTy>
  141. static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) {
  142. return Create(Key, Allocator, ValueTy());
  143. }
  144. /// Create - Create a StringMapEntry with normal malloc/free.
  145. template<typename InitType>
  146. static StringMapEntry *Create(StringRef Key, InitType &&InitVal) {
  147. MallocAllocator A;
  148. return Create(Key, A, std::forward<InitType>(InitVal));
  149. }
  150. static StringMapEntry *Create(StringRef Key) {
  151. return Create(Key, ValueTy());
  152. }
  153. /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
  154. /// into a StringMapEntry, return the StringMapEntry itself.
  155. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
  156. char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
  157. return *reinterpret_cast<StringMapEntry*>(Ptr);
  158. }
  159. /// Destroy - Destroy this StringMapEntry, releasing memory back to the
  160. /// specified allocator.
  161. template<typename AllocatorTy>
  162. void Destroy(AllocatorTy &Allocator) {
  163. // Free memory referenced by the item.
  164. unsigned AllocSize =
  165. static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1;
  166. this->~StringMapEntry();
  167. Allocator.Deallocate(static_cast<void *>(this), AllocSize);
  168. }
  169. /// Destroy this object, releasing memory back to the malloc allocator.
  170. void Destroy() {
  171. MallocAllocator A;
  172. Destroy(A);
  173. }
  174. };
  175. /// StringMap - This is an unconventional map that is specialized for handling
  176. /// keys that are "strings", which are basically ranges of bytes. This does some
  177. /// funky memory allocation and hashing things to make it extremely efficient,
  178. /// storing the string data *after* the value in the map.
  179. template<typename ValueTy, typename AllocatorTy = MallocAllocator>
  180. class StringMap : public StringMapImpl {
  181. AllocatorTy Allocator;
  182. public:
  183. typedef StringMapEntry<ValueTy> MapEntryTy;
  184. StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
  185. explicit StringMap(unsigned InitialSize)
  186. : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
  187. explicit StringMap(AllocatorTy A)
  188. : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
  189. StringMap(unsigned InitialSize, AllocatorTy A)
  190. : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
  191. Allocator(A) {}
  192. StringMap(StringMap &&RHS)
  193. : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
  194. StringMap &operator=(StringMap RHS) {
  195. StringMapImpl::swap(RHS);
  196. std::swap(Allocator, RHS.Allocator);
  197. return *this;
  198. }
  199. // FIXME: Implement copy operations if/when they're needed.
  200. AllocatorTy &getAllocator() { return Allocator; }
  201. const AllocatorTy &getAllocator() const { return Allocator; }
  202. typedef const char* key_type;
  203. typedef ValueTy mapped_type;
  204. typedef StringMapEntry<ValueTy> value_type;
  205. typedef size_t size_type;
  206. typedef StringMapConstIterator<ValueTy> const_iterator;
  207. typedef StringMapIterator<ValueTy> iterator;
  208. iterator begin() {
  209. return iterator(TheTable, NumBuckets == 0);
  210. }
  211. iterator end() {
  212. return iterator(TheTable+NumBuckets, true);
  213. }
  214. const_iterator begin() const {
  215. return const_iterator(TheTable, NumBuckets == 0);
  216. }
  217. const_iterator end() const {
  218. return const_iterator(TheTable+NumBuckets, true);
  219. }
  220. iterator find(StringRef Key) {
  221. int Bucket = FindKey(Key);
  222. if (Bucket == -1) return end();
  223. return iterator(TheTable+Bucket, true);
  224. }
  225. const_iterator find(StringRef Key) const {
  226. int Bucket = FindKey(Key);
  227. if (Bucket == -1) return end();
  228. return const_iterator(TheTable+Bucket, true);
  229. }
  230. /// lookup - Return the entry for the specified key, or a default
  231. /// constructed value if no such entry exists.
  232. ValueTy lookup(StringRef Key) const {
  233. const_iterator it = find(Key);
  234. if (it != end())
  235. return it->second;
  236. return ValueTy();
  237. }
  238. ValueTy &operator[](StringRef Key) {
  239. return insert(std::make_pair(Key, ValueTy())).first->second;
  240. }
  241. /// count - Return 1 if the element is in the map, 0 otherwise.
  242. size_type count(StringRef Key) const {
  243. return find(Key) == end() ? 0 : 1;
  244. }
  245. /// insert - Insert the specified key/value pair into the map. If the key
  246. /// already exists in the map, return false and ignore the request, otherwise
  247. /// insert it and return true.
  248. bool insert(MapEntryTy *KeyValue) {
  249. unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
  250. StringMapEntryBase *&Bucket = TheTable[BucketNo];
  251. if (Bucket && Bucket != getTombstoneVal())
  252. return false; // Already exists in map.
  253. if (Bucket == getTombstoneVal())
  254. --NumTombstones;
  255. Bucket = KeyValue;
  256. ++NumItems;
  257. assert(NumItems + NumTombstones <= NumBuckets);
  258. RehashTable();
  259. return true;
  260. }
  261. /// insert - Inserts the specified key/value pair into the map if the key
  262. /// isn't already in the map. The bool component of the returned pair is true
  263. /// if and only if the insertion takes place, and the iterator component of
  264. /// the pair points to the element with key equivalent to the key of the pair.
  265. std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
  266. unsigned BucketNo = LookupBucketFor(KV.first);
  267. StringMapEntryBase *&Bucket = TheTable[BucketNo];
  268. if (Bucket && Bucket != getTombstoneVal())
  269. return std::make_pair(iterator(TheTable + BucketNo, false),
  270. false); // Already exists in map.
  271. if (Bucket == getTombstoneVal())
  272. --NumTombstones;
  273. Bucket =
  274. MapEntryTy::Create(KV.first, Allocator, std::move(KV.second));
  275. ++NumItems;
  276. assert(NumItems + NumTombstones <= NumBuckets);
  277. BucketNo = RehashTable(BucketNo);
  278. return std::make_pair(iterator(TheTable + BucketNo, false), true);
  279. }
  280. // clear - Empties out the StringMap
  281. void clear() {
  282. if (empty()) return;
  283. // Zap all values, resetting the keys back to non-present (not tombstone),
  284. // which is safe because we're removing all elements.
  285. for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
  286. StringMapEntryBase *&Bucket = TheTable[I];
  287. if (Bucket && Bucket != getTombstoneVal()) {
  288. static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
  289. }
  290. Bucket = nullptr;
  291. }
  292. NumItems = 0;
  293. NumTombstones = 0;
  294. }
  295. /// remove - Remove the specified key/value pair from the map, but do not
  296. /// erase it. This aborts if the key is not in the map.
  297. void remove(MapEntryTy *KeyValue) {
  298. RemoveKey(KeyValue);
  299. }
  300. void erase(iterator I) {
  301. MapEntryTy &V = *I;
  302. remove(&V);
  303. V.Destroy(Allocator);
  304. }
  305. bool erase(StringRef Key) {
  306. iterator I = find(Key);
  307. if (I == end()) return false;
  308. erase(I);
  309. return true;
  310. }
  311. ~StringMap() {
  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.
  315. if (!empty()) {
  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);
  320. }
  321. }
  322. }
  323. free(TheTable);
  324. }
  325. };
  326. template<typename ValueTy>
  327. class StringMapConstIterator {
  328. protected:
  329. StringMapEntryBase **Ptr;
  330. public:
  331. typedef StringMapEntry<ValueTy> value_type;
  332. StringMapConstIterator() : Ptr(nullptr) { }
  333. explicit StringMapConstIterator(StringMapEntryBase **Bucket,
  334. bool NoAdvance = false)
  335. : Ptr(Bucket) {
  336. if (!NoAdvance) AdvancePastEmptyBuckets();
  337. }
  338. const value_type &operator*() const {
  339. return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
  340. }
  341. const value_type *operator->() const {
  342. return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
  343. }
  344. bool operator==(const StringMapConstIterator &RHS) const {
  345. return Ptr == RHS.Ptr;
  346. }
  347. bool operator!=(const StringMapConstIterator &RHS) const {
  348. return Ptr != RHS.Ptr;
  349. }
  350. inline StringMapConstIterator& operator++() { // Preincrement
  351. ++Ptr;
  352. AdvancePastEmptyBuckets();
  353. return *this;
  354. }
  355. StringMapConstIterator operator++(int) { // Postincrement
  356. StringMapConstIterator tmp = *this; ++*this; return tmp;
  357. }
  358. private:
  359. void AdvancePastEmptyBuckets() {
  360. while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
  361. ++Ptr;
  362. }
  363. };
  364. template<typename ValueTy>
  365. class StringMapIterator : public StringMapConstIterator<ValueTy> {
  366. public:
  367. StringMapIterator() {}
  368. explicit StringMapIterator(StringMapEntryBase **Bucket,
  369. bool NoAdvance = false)
  370. : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
  371. }
  372. StringMapEntry<ValueTy> &operator*() const {
  373. return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
  374. }
  375. StringMapEntry<ValueTy> *operator->() const {
  376. return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
  377. }
  378. };
  379. }
  380. #endif