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