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