LLVM API Documentation
00001 //===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the StringMap class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_ADT_STRINGMAP_H 00015 #define LLVM_ADT_STRINGMAP_H 00016 00017 #include "llvm/ADT/StringRef.h" 00018 #include "llvm/Support/Allocator.h" 00019 #include <cstring> 00020 #include <utility> 00021 00022 namespace llvm { 00023 template<typename ValueT> 00024 class StringMapConstIterator; 00025 template<typename ValueT> 00026 class StringMapIterator; 00027 template<typename ValueTy> 00028 class StringMapEntry; 00029 00030 /// StringMapEntryBase - Shared base class of StringMapEntry instances. 00031 class StringMapEntryBase { 00032 unsigned StrLen; 00033 public: 00034 explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} 00035 00036 unsigned getKeyLength() const { return StrLen; } 00037 }; 00038 00039 /// StringMapImpl - This is the base class of StringMap that is shared among 00040 /// all of its instantiations. 00041 class StringMapImpl { 00042 protected: 00043 // Array of NumBuckets pointers to entries, null pointers are holes. 00044 // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed 00045 // by an array of the actual hash values as unsigned integers. 00046 StringMapEntryBase **TheTable; 00047 unsigned NumBuckets; 00048 unsigned NumItems; 00049 unsigned NumTombstones; 00050 unsigned ItemSize; 00051 protected: 00052 explicit StringMapImpl(unsigned itemSize) 00053 : TheTable(nullptr), 00054 // Initialize the map with zero buckets to allocation. 00055 NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} 00056 StringMapImpl(StringMapImpl &&RHS) 00057 : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), 00058 NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), 00059 ItemSize(RHS.ItemSize) { 00060 RHS.TheTable = nullptr; 00061 RHS.NumBuckets = 0; 00062 RHS.NumItems = 0; 00063 RHS.NumTombstones = 0; 00064 } 00065 00066 StringMapImpl(unsigned InitSize, unsigned ItemSize); 00067 unsigned RehashTable(unsigned BucketNo = 0); 00068 00069 /// LookupBucketFor - Look up the bucket that the specified string should end 00070 /// up in. If it already exists as a key in the map, the Item pointer for the 00071 /// specified bucket will be non-null. Otherwise, it will be null. In either 00072 /// case, the FullHashValue field of the bucket will be set to the hash value 00073 /// of the string. 00074 unsigned LookupBucketFor(StringRef Key); 00075 00076 /// FindKey - Look up the bucket that contains the specified key. If it exists 00077 /// in the map, return the bucket number of the key. Otherwise return -1. 00078 /// This does not modify the map. 00079 int FindKey(StringRef Key) const; 00080 00081 /// RemoveKey - Remove the specified StringMapEntry from the table, but do not 00082 /// delete it. This aborts if the value isn't in the table. 00083 void RemoveKey(StringMapEntryBase *V); 00084 00085 /// RemoveKey - Remove the StringMapEntry for the specified key from the 00086 /// table, returning it. If the key is not in the table, this returns null. 00087 StringMapEntryBase *RemoveKey(StringRef Key); 00088 private: 00089 void init(unsigned Size); 00090 public: 00091 static StringMapEntryBase *getTombstoneVal() { 00092 return (StringMapEntryBase*)-1; 00093 } 00094 00095 unsigned getNumBuckets() const { return NumBuckets; } 00096 unsigned getNumItems() const { return NumItems; } 00097 00098 bool empty() const { return NumItems == 0; } 00099 unsigned size() const { return NumItems; } 00100 00101 void swap(StringMapImpl &Other) { 00102 std::swap(TheTable, Other.TheTable); 00103 std::swap(NumBuckets, Other.NumBuckets); 00104 std::swap(NumItems, Other.NumItems); 00105 std::swap(NumTombstones, Other.NumTombstones); 00106 } 00107 }; 00108 00109 /// StringMapEntry - This is used to represent one value that is inserted into 00110 /// a StringMap. It contains the Value itself and the key: the string length 00111 /// and data. 00112 template<typename ValueTy> 00113 class StringMapEntry : public StringMapEntryBase { 00114 StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION; 00115 public: 00116 ValueTy second; 00117 00118 explicit StringMapEntry(unsigned strLen) 00119 : StringMapEntryBase(strLen), second() {} 00120 StringMapEntry(unsigned strLen, ValueTy V) 00121 : StringMapEntryBase(strLen), second(std::move(V)) {} 00122 00123 StringRef getKey() const { 00124 return StringRef(getKeyData(), getKeyLength()); 00125 } 00126 00127 const ValueTy &getValue() const { return second; } 00128 ValueTy &getValue() { return second; } 00129 00130 void setValue(const ValueTy &V) { second = V; } 00131 00132 /// getKeyData - Return the start of the string data that is the key for this 00133 /// value. The string data is always stored immediately after the 00134 /// StringMapEntry object. 00135 const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} 00136 00137 StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } 00138 00139 /// Create - Create a StringMapEntry for the specified key and default 00140 /// construct the value. 00141 template<typename AllocatorTy, typename InitType> 00142 static StringMapEntry *Create(StringRef Key, 00143 AllocatorTy &Allocator, 00144 InitType InitVal) { 00145 unsigned KeyLength = Key.size(); 00146 00147 // Allocate a new item with space for the string at the end and a null 00148 // terminator. 00149 unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ 00150 KeyLength+1; 00151 unsigned Alignment = alignOf<StringMapEntry>(); 00152 00153 StringMapEntry *NewItem = 00154 static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); 00155 00156 // Default construct the value. 00157 new (NewItem) StringMapEntry(KeyLength, std::move(InitVal)); 00158 00159 // Copy the string information. 00160 char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); 00161 memcpy(StrBuffer, Key.data(), KeyLength); 00162 StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. 00163 return NewItem; 00164 } 00165 00166 template<typename AllocatorTy> 00167 static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { 00168 return Create(Key, Allocator, ValueTy()); 00169 } 00170 00171 /// Create - Create a StringMapEntry with normal malloc/free. 00172 template<typename InitType> 00173 static StringMapEntry *Create(StringRef Key, InitType InitVal) { 00174 MallocAllocator A; 00175 return Create(Key, A, std::move(InitVal)); 00176 } 00177 00178 static StringMapEntry *Create(StringRef Key) { 00179 return Create(Key, ValueTy()); 00180 } 00181 00182 /// GetStringMapEntryFromValue - Given a value that is known to be embedded 00183 /// into a StringMapEntry, return the StringMapEntry itself. 00184 static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { 00185 StringMapEntry *EPtr = 0; 00186 char *Ptr = reinterpret_cast<char*>(&V) - 00187 (reinterpret_cast<char*>(&EPtr->second) - 00188 reinterpret_cast<char*>(EPtr)); 00189 return *reinterpret_cast<StringMapEntry*>(Ptr); 00190 } 00191 static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { 00192 return GetStringMapEntryFromValue(const_cast<ValueTy&>(V)); 00193 } 00194 00195 /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded 00196 /// into a StringMapEntry, return the StringMapEntry itself. 00197 static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { 00198 char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>); 00199 return *reinterpret_cast<StringMapEntry*>(Ptr); 00200 } 00201 00202 /// Destroy - Destroy this StringMapEntry, releasing memory back to the 00203 /// specified allocator. 00204 template<typename AllocatorTy> 00205 void Destroy(AllocatorTy &Allocator) { 00206 // Free memory referenced by the item. 00207 unsigned AllocSize = 00208 static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1; 00209 this->~StringMapEntry(); 00210 Allocator.Deallocate(static_cast<void *>(this), AllocSize); 00211 } 00212 00213 /// Destroy this object, releasing memory back to the malloc allocator. 00214 void Destroy() { 00215 MallocAllocator A; 00216 Destroy(A); 00217 } 00218 }; 00219 00220 00221 /// StringMap - This is an unconventional map that is specialized for handling 00222 /// keys that are "strings", which are basically ranges of bytes. This does some 00223 /// funky memory allocation and hashing things to make it extremely efficient, 00224 /// storing the string data *after* the value in the map. 00225 template<typename ValueTy, typename AllocatorTy = MallocAllocator> 00226 class StringMap : public StringMapImpl { 00227 AllocatorTy Allocator; 00228 public: 00229 typedef StringMapEntry<ValueTy> MapEntryTy; 00230 00231 StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} 00232 explicit StringMap(unsigned InitialSize) 00233 : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} 00234 00235 explicit StringMap(AllocatorTy A) 00236 : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} 00237 00238 StringMap(unsigned InitialSize, AllocatorTy A) 00239 : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), 00240 Allocator(A) {} 00241 00242 StringMap(StringMap &&RHS) 00243 : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} 00244 00245 StringMap &operator=(StringMap RHS) { 00246 StringMapImpl::swap(RHS); 00247 std::swap(Allocator, RHS.Allocator); 00248 return *this; 00249 } 00250 00251 // FIXME: Implement copy operations if/when they're needed. 00252 00253 AllocatorTy &getAllocator() { return Allocator; } 00254 const AllocatorTy &getAllocator() const { return Allocator; } 00255 00256 typedef const char* key_type; 00257 typedef ValueTy mapped_type; 00258 typedef StringMapEntry<ValueTy> value_type; 00259 typedef size_t size_type; 00260 00261 typedef StringMapConstIterator<ValueTy> const_iterator; 00262 typedef StringMapIterator<ValueTy> iterator; 00263 00264 iterator begin() { 00265 return iterator(TheTable, NumBuckets == 0); 00266 } 00267 iterator end() { 00268 return iterator(TheTable+NumBuckets, true); 00269 } 00270 const_iterator begin() const { 00271 return const_iterator(TheTable, NumBuckets == 0); 00272 } 00273 const_iterator end() const { 00274 return const_iterator(TheTable+NumBuckets, true); 00275 } 00276 00277 iterator find(StringRef Key) { 00278 int Bucket = FindKey(Key); 00279 if (Bucket == -1) return end(); 00280 return iterator(TheTable+Bucket, true); 00281 } 00282 00283 const_iterator find(StringRef Key) const { 00284 int Bucket = FindKey(Key); 00285 if (Bucket == -1) return end(); 00286 return const_iterator(TheTable+Bucket, true); 00287 } 00288 00289 /// lookup - Return the entry for the specified key, or a default 00290 /// constructed value if no such entry exists. 00291 ValueTy lookup(StringRef Key) const { 00292 const_iterator it = find(Key); 00293 if (it != end()) 00294 return it->second; 00295 return ValueTy(); 00296 } 00297 00298 ValueTy &operator[](StringRef Key) { 00299 return GetOrCreateValue(Key).getValue(); 00300 } 00301 00302 /// count - Return 1 if the element is in the map, 0 otherwise. 00303 size_type count(StringRef Key) const { 00304 return find(Key) == end() ? 0 : 1; 00305 } 00306 00307 /// insert - Insert the specified key/value pair into the map. If the key 00308 /// already exists in the map, return false and ignore the request, otherwise 00309 /// insert it and return true. 00310 bool insert(MapEntryTy *KeyValue) { 00311 unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); 00312 StringMapEntryBase *&Bucket = TheTable[BucketNo]; 00313 if (Bucket && Bucket != getTombstoneVal()) 00314 return false; // Already exists in map. 00315 00316 if (Bucket == getTombstoneVal()) 00317 --NumTombstones; 00318 Bucket = KeyValue; 00319 ++NumItems; 00320 assert(NumItems + NumTombstones <= NumBuckets); 00321 00322 RehashTable(); 00323 return true; 00324 } 00325 00326 /// insert - Inserts the specified key/value pair into the map if the key 00327 /// isn't already in the map. The bool component of the returned pair is true 00328 /// if and only if the insertion takes place, and the iterator component of 00329 /// the pair points to the element with key equivalent to the key of the pair. 00330 std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) { 00331 unsigned BucketNo = LookupBucketFor(KV.first); 00332 StringMapEntryBase *&Bucket = TheTable[BucketNo]; 00333 if (Bucket && Bucket != getTombstoneVal()) 00334 return std::make_pair(iterator(TheTable + BucketNo, false), 00335 false); // Already exists in map. 00336 00337 if (Bucket == getTombstoneVal()) 00338 --NumTombstones; 00339 Bucket = 00340 MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); 00341 ++NumItems; 00342 assert(NumItems + NumTombstones <= NumBuckets); 00343 00344 BucketNo = RehashTable(BucketNo); 00345 return std::make_pair(iterator(TheTable + BucketNo, false), true); 00346 } 00347 00348 // clear - Empties out the StringMap 00349 void clear() { 00350 if (empty()) return; 00351 00352 // Zap all values, resetting the keys back to non-present (not tombstone), 00353 // which is safe because we're removing all elements. 00354 for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 00355 StringMapEntryBase *&Bucket = TheTable[I]; 00356 if (Bucket && Bucket != getTombstoneVal()) { 00357 static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); 00358 } 00359 Bucket = nullptr; 00360 } 00361 00362 NumItems = 0; 00363 NumTombstones = 0; 00364 } 00365 00366 /// GetOrCreateValue - Look up the specified key in the table. If a value 00367 /// exists, return it. Otherwise, default construct a value, insert it, and 00368 /// return. 00369 template <typename InitTy> 00370 MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) { 00371 return *insert(std::make_pair(Key, std::move(Val))).first; 00372 } 00373 00374 MapEntryTy &GetOrCreateValue(StringRef Key) { 00375 return GetOrCreateValue(Key, ValueTy()); 00376 } 00377 00378 /// remove - Remove the specified key/value pair from the map, but do not 00379 /// erase it. This aborts if the key is not in the map. 00380 void remove(MapEntryTy *KeyValue) { 00381 RemoveKey(KeyValue); 00382 } 00383 00384 void erase(iterator I) { 00385 MapEntryTy &V = *I; 00386 remove(&V); 00387 V.Destroy(Allocator); 00388 } 00389 00390 bool erase(StringRef Key) { 00391 iterator I = find(Key); 00392 if (I == end()) return false; 00393 erase(I); 00394 return true; 00395 } 00396 00397 ~StringMap() { 00398 // Delete all the elements in the map, but don't reset the elements 00399 // to default values. This is a copy of clear(), but avoids unnecessary 00400 // work not required in the destructor. 00401 if (!empty()) { 00402 for (unsigned I = 0, E = NumBuckets; I != E; ++I) { 00403 StringMapEntryBase *Bucket = TheTable[I]; 00404 if (Bucket && Bucket != getTombstoneVal()) { 00405 static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); 00406 } 00407 } 00408 } 00409 free(TheTable); 00410 } 00411 }; 00412 00413 00414 template<typename ValueTy> 00415 class StringMapConstIterator { 00416 protected: 00417 StringMapEntryBase **Ptr; 00418 public: 00419 typedef StringMapEntry<ValueTy> value_type; 00420 00421 StringMapConstIterator() : Ptr(nullptr) { } 00422 00423 explicit StringMapConstIterator(StringMapEntryBase **Bucket, 00424 bool NoAdvance = false) 00425 : Ptr(Bucket) { 00426 if (!NoAdvance) AdvancePastEmptyBuckets(); 00427 } 00428 00429 const value_type &operator*() const { 00430 return *static_cast<StringMapEntry<ValueTy>*>(*Ptr); 00431 } 00432 const value_type *operator->() const { 00433 return static_cast<StringMapEntry<ValueTy>*>(*Ptr); 00434 } 00435 00436 bool operator==(const StringMapConstIterator &RHS) const { 00437 return Ptr == RHS.Ptr; 00438 } 00439 bool operator!=(const StringMapConstIterator &RHS) const { 00440 return Ptr != RHS.Ptr; 00441 } 00442 00443 inline StringMapConstIterator& operator++() { // Preincrement 00444 ++Ptr; 00445 AdvancePastEmptyBuckets(); 00446 return *this; 00447 } 00448 StringMapConstIterator operator++(int) { // Postincrement 00449 StringMapConstIterator tmp = *this; ++*this; return tmp; 00450 } 00451 00452 private: 00453 void AdvancePastEmptyBuckets() { 00454 while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) 00455 ++Ptr; 00456 } 00457 }; 00458 00459 template<typename ValueTy> 00460 class StringMapIterator : public StringMapConstIterator<ValueTy> { 00461 public: 00462 StringMapIterator() {} 00463 explicit StringMapIterator(StringMapEntryBase **Bucket, 00464 bool NoAdvance = false) 00465 : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { 00466 } 00467 StringMapEntry<ValueTy> &operator*() const { 00468 return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); 00469 } 00470 StringMapEntry<ValueTy> *operator->() const { 00471 return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); 00472 } 00473 }; 00474 00475 } 00476 00477 #endif