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, (void*)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, (void*)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 00350 /// GetOrCreateValue - Look up the specified key in the table. If a value 00351 /// exists, return it. Otherwise, default construct a value, insert it, and 00352 /// return. 00353 template <typename InitTy> 00354 StringMapEntry<ValueTy> &GetOrCreateValue(const char *KeyStart, 00355 const char *KeyEnd, 00356 InitTy Val) { 00357 unsigned BucketNo = LookupBucketFor(KeyStart, KeyEnd); 00358 ItemBucket &Bucket = TheTable[BucketNo]; 00359 if (Bucket.Item && Bucket.Item != getTombstoneVal()) 00360 return *static_cast<MapEntryTy*>(Bucket.Item); 00361 00362 MapEntryTy *NewItem = MapEntryTy::Create(KeyStart, KeyEnd, Allocator, Val); 00363 00364 if (Bucket.Item == getTombstoneVal()) 00365 --NumTombstones; 00366 ++NumItems; 00367 00368 // Fill in the bucket for the hash table. The FullHashValue was already 00369 // filled in by LookupBucketFor. 00370 Bucket.Item = NewItem; 00371 00372 if (ShouldRehash()) 00373 RehashTable(); 00374 return *NewItem; 00375 } 00376 00377 StringMapEntry<ValueTy> &GetOrCreateValue(const char *KeyStart, 00378 const char *KeyEnd) { 00379 return GetOrCreateValue(KeyStart, KeyEnd, (void*)0); 00380 } 00381 00382 /// remove - Remove the specified key/value pair from the map, but do not 00383 /// erase it. This aborts if the key is not in the map. 00384 void remove(MapEntryTy *KeyValue) { 00385 RemoveKey(KeyValue); 00386 } 00387 00388 void erase(iterator I) { 00389 MapEntryTy &V = *I; 00390 remove(&V); 00391 V.Destroy(Allocator); 00392 } 00393 00394 bool erase(const char *Key) { 00395 iterator I = find(Key); 00396 if (I == end()) return false; 00397 erase(I); 00398 return true; 00399 } 00400 00401 bool erase(const std::string &Key) { 00402 iterator I = find(Key); 00403 if (I == end()) return false; 00404 erase(I); 00405 return true; 00406 } 00407 00408 ~StringMap() { 00409 clear(); 00410 free(TheTable); 00411 } 00412 private: 00413 StringMap(const StringMap &); // FIXME: Implement. 00414 void operator=(const StringMap &); // FIXME: Implement. 00415 }; 00416 00417 00418 template<typename ValueTy> 00419 class StringMapConstIterator { 00420 protected: 00421 StringMapImpl::ItemBucket *Ptr; 00422 public: 00423 typedef StringMapEntry<ValueTy> value_type; 00424 00425 explicit StringMapConstIterator(StringMapImpl::ItemBucket *Bucket, 00426 bool NoAdvance = false) 00427 : Ptr(Bucket) { 00428 if (!NoAdvance) AdvancePastEmptyBuckets(); 00429 } 00430 00431 const value_type &operator*() const { 00432 return *static_cast<StringMapEntry<ValueTy>*>(Ptr->Item); 00433 } 00434 const value_type *operator->() const { 00435 return static_cast<StringMapEntry<ValueTy>*>(Ptr->Item); 00436 } 00437 00438 bool operator==(const StringMapConstIterator &RHS) const { 00439 return Ptr == RHS.Ptr; 00440 } 00441 bool operator!=(const StringMapConstIterator &RHS) const { 00442 return Ptr != RHS.Ptr; 00443 } 00444 00445 inline StringMapConstIterator& operator++() { // Preincrement 00446 ++Ptr; 00447 AdvancePastEmptyBuckets(); 00448 return *this; 00449 } 00450 StringMapConstIterator operator++(int) { // Postincrement 00451 StringMapConstIterator tmp = *this; ++*this; return tmp; 00452 } 00453 00454 private: 00455 void AdvancePastEmptyBuckets() { 00456 while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal()) 00457 ++Ptr; 00458 } 00459 }; 00460 00461 template<typename ValueTy> 00462 class StringMapIterator : public StringMapConstIterator<ValueTy> { 00463 public: 00464 explicit StringMapIterator(StringMapImpl::ItemBucket *Bucket, 00465 bool NoAdvance = false) 00466 : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { 00467 } 00468 StringMapEntry<ValueTy> &operator*() const { 00469 return *static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item); 00470 } 00471 StringMapEntry<ValueTy> *operator->() const { 00472 return static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item); 00473 } 00474 }; 00475 00476 } 00477 00478 #endif
This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.