LLVM API Documentation

StringMap.h

Go to the documentation of this file.
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.