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