LCOV - code coverage report
Current view: top level - llvm/ADT - StringMap.h (source / functions) Hit Total Coverage
Test: clang.info Lines: 19 19 100.0 %
Date: 2016-01-31 12:01:00 Functions: 9 9 100.0 %

          Line data    Source code
       1             : //===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file defines the StringMap class.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_ADT_STRINGMAP_H
      15             : #define LLVM_ADT_STRINGMAP_H
      16             : 
      17             : #include "llvm/ADT/StringRef.h"
      18             : #include "llvm/Support/Allocator.h"
      19             : #include <cstring>
      20             : #include <utility>
      21             : 
      22             : namespace llvm {
      23             :   template<typename ValueT>
      24             :   class StringMapConstIterator;
      25             :   template<typename ValueT>
      26             :   class StringMapIterator;
      27             :   template<typename ValueTy>
      28             :   class StringMapEntry;
      29             : 
      30             : /// StringMapEntryBase - Shared base class of StringMapEntry instances.
      31             : class StringMapEntryBase {
      32             :   unsigned StrLen;
      33             : public:
      34             :   explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
      35             : 
      36          24 :   unsigned getKeyLength() const { return StrLen; }
      37             : };
      38             : 
      39             : /// StringMapImpl - This is the base class of StringMap that is shared among
      40             : /// all of its instantiations.
      41             : class StringMapImpl {
      42             : protected:
      43             :   // Array of NumBuckets pointers to entries, null pointers are holes.
      44             :   // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
      45             :   // by an array of the actual hash values as unsigned integers.
      46             :   StringMapEntryBase **TheTable;
      47             :   unsigned NumBuckets;
      48             :   unsigned NumItems;
      49             :   unsigned NumTombstones;
      50             :   unsigned ItemSize;
      51             : protected:
      52             :   explicit StringMapImpl(unsigned itemSize)
      53             :       : TheTable(nullptr),
      54             :         // Initialize the map with zero buckets to allocation.
      55             :         NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {}
      56             :   StringMapImpl(StringMapImpl &&RHS)
      57             :       : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
      58             :         NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
      59             :         ItemSize(RHS.ItemSize) {
      60             :     RHS.TheTable = nullptr;
      61             :     RHS.NumBuckets = 0;
      62             :     RHS.NumItems = 0;
      63             :     RHS.NumTombstones = 0;
      64             :   }
      65             : 
      66             :   StringMapImpl(unsigned InitSize, unsigned ItemSize);
      67             :   unsigned RehashTable(unsigned BucketNo = 0);
      68             : 
      69             :   /// LookupBucketFor - Look up the bucket that the specified string should end
      70             :   /// up in.  If it already exists as a key in the map, the Item pointer for the
      71             :   /// specified bucket will be non-null.  Otherwise, it will be null.  In either
      72             :   /// case, the FullHashValue field of the bucket will be set to the hash value
      73             :   /// of the string.
      74             :   unsigned LookupBucketFor(StringRef Key);
      75             : 
      76             :   /// FindKey - Look up the bucket that contains the specified key. If it exists
      77             :   /// in the map, return the bucket number of the key.  Otherwise return -1.
      78             :   /// This does not modify the map.
      79             :   int FindKey(StringRef Key) const;
      80             : 
      81             :   /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
      82             :   /// delete it.  This aborts if the value isn't in the table.
      83             :   void RemoveKey(StringMapEntryBase *V);
      84             : 
      85             :   /// RemoveKey - Remove the StringMapEntry for the specified key from the
      86             :   /// table, returning it.  If the key is not in the table, this returns null.
      87             :   StringMapEntryBase *RemoveKey(StringRef Key);
      88             : private:
      89             :   void init(unsigned Size);
      90             : public:
      91             :   static StringMapEntryBase *getTombstoneVal() {
      92          48 :     return (StringMapEntryBase*)-1;
      93             :   }
      94             : 
      95             :   unsigned getNumBuckets() const { return NumBuckets; }
      96             :   unsigned getNumItems() const { return NumItems; }
      97             : 
      98          24 :   bool empty() const { return NumItems == 0; }
      99             :   unsigned size() const { return NumItems; }
     100             : 
     101             :   void swap(StringMapImpl &Other) {
     102             :     std::swap(TheTable, Other.TheTable);
     103             :     std::swap(NumBuckets, Other.NumBuckets);
     104             :     std::swap(NumItems, Other.NumItems);
     105             :     std::swap(NumTombstones, Other.NumTombstones);
     106             :   }
     107             : };
     108             : 
     109             : /// StringMapEntry - This is used to represent one value that is inserted into
     110             : /// a StringMap.  It contains the Value itself and the key: the string length
     111             : /// and data.
     112             : template<typename ValueTy>
     113          24 : class StringMapEntry : public StringMapEntryBase {
     114             :   StringMapEntry(StringMapEntry &E) = delete;
     115             : public:
     116             :   ValueTy second;
     117             : 
     118             :   explicit StringMapEntry(unsigned strLen)
     119             :     : StringMapEntryBase(strLen), second() {}
     120             :   template <class InitTy>
     121             :   StringMapEntry(unsigned strLen, InitTy &&V)
     122             :       : StringMapEntryBase(strLen), second(std::forward<InitTy>(V)) {}
     123             : 
     124             :   StringRef getKey() const {
     125             :     return StringRef(getKeyData(), getKeyLength());
     126             :   }
     127             : 
     128             :   const ValueTy &getValue() const { return second; }
     129             :   ValueTy &getValue() { return second; }
     130             : 
     131             :   void setValue(const ValueTy &V) { second = V; }
     132             : 
     133             :   /// getKeyData - Return the start of the string data that is the key for this
     134             :   /// value.  The string data is always stored immediately after the
     135             :   /// StringMapEntry object.
     136             :   const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
     137             : 
     138             :   StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
     139             : 
     140             :   /// Create - Create a StringMapEntry for the specified key and default
     141             :   /// construct the value.
     142             :   template <typename AllocatorTy, typename InitType>
     143             :   static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
     144             :                                 InitType &&InitVal) {
     145             :     unsigned KeyLength = Key.size();
     146             : 
     147             :     // Allocate a new item with space for the string at the end and a null
     148             :     // terminator.
     149             :     unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
     150             :       KeyLength+1;
     151             :     unsigned Alignment = alignOf<StringMapEntry>();
     152             : 
     153             :     StringMapEntry *NewItem =
     154             :       static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
     155             : 
     156             :     // Default construct the value.
     157             :     new (NewItem) StringMapEntry(KeyLength, std::forward<InitType>(InitVal));
     158             : 
     159             :     // Copy the string information.
     160             :     char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
     161             :     if (KeyLength > 0)
     162             :       memcpy(StrBuffer, Key.data(), KeyLength);
     163             :     StrBuffer[KeyLength] = 0;  // Null terminate for convenience of clients.
     164             :     return NewItem;
     165             :   }
     166             : 
     167             :   template<typename AllocatorTy>
     168             :   static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) {
     169             :     return Create(Key, Allocator, ValueTy());
     170             :   }
     171             : 
     172             :   /// Create - Create a StringMapEntry with normal malloc/free.
     173             :   template<typename InitType>
     174             :   static StringMapEntry *Create(StringRef Key, InitType &&InitVal) {
     175             :     MallocAllocator A;
     176             :     return Create(Key, A, std::forward<InitType>(InitVal));
     177             :   }
     178             : 
     179             :   static StringMapEntry *Create(StringRef Key) {
     180             :     return Create(Key, ValueTy());
     181             :   }
     182             : 
     183             :   /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
     184             :   /// into a StringMapEntry, return the StringMapEntry itself.
     185             :   static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
     186             :     char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
     187             :     return *reinterpret_cast<StringMapEntry*>(Ptr);
     188             :   }
     189             : 
     190             :   /// Destroy - Destroy this StringMapEntry, releasing memory back to the
     191             :   /// specified allocator.
     192             :   template<typename AllocatorTy>
     193             :   void Destroy(AllocatorTy &Allocator) {
     194             :     // Free memory referenced by the item.
     195          24 :     unsigned AllocSize =
     196          24 :         static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1;
     197          24 :     this->~StringMapEntry();
     198          24 :     Allocator.Deallocate(static_cast<void *>(this), AllocSize);
     199          24 :   }
     200             : 
     201             :   /// Destroy this object, releasing memory back to the malloc allocator.
     202             :   void Destroy() {
     203             :     MallocAllocator A;
     204             :     Destroy(A);
     205             :   }
     206             : };
     207             : 
     208             : 
     209             : /// StringMap - This is an unconventional map that is specialized for handling
     210             : /// keys that are "strings", which are basically ranges of bytes. This does some
     211             : /// funky memory allocation and hashing things to make it extremely efficient,
     212             : /// storing the string data *after* the value in the map.
     213             : template<typename ValueTy, typename AllocatorTy = MallocAllocator>
     214             : class StringMap : public StringMapImpl {
     215             :   AllocatorTy Allocator;
     216             : public:
     217             :   typedef StringMapEntry<ValueTy> MapEntryTy;
     218             :   
     219             :   StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
     220             :   explicit StringMap(unsigned InitialSize)
     221             :     : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
     222             : 
     223             :   explicit StringMap(AllocatorTy A)
     224             :     : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
     225             : 
     226             :   StringMap(unsigned InitialSize, AllocatorTy A)
     227             :     : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
     228             :       Allocator(A) {}
     229             : 
     230             :   StringMap(StringMap &&RHS)
     231             :       : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
     232             : 
     233             :   StringMap &operator=(StringMap RHS) {
     234             :     StringMapImpl::swap(RHS);
     235             :     std::swap(Allocator, RHS.Allocator);
     236             :     return *this;
     237             :   }
     238             : 
     239             :   // FIXME: Implement copy operations if/when they're needed.
     240             : 
     241             :   AllocatorTy &getAllocator() { return Allocator; }
     242             :   const AllocatorTy &getAllocator() const { return Allocator; }
     243             : 
     244             :   typedef const char* key_type;
     245             :   typedef ValueTy mapped_type;
     246             :   typedef StringMapEntry<ValueTy> value_type;
     247             :   typedef size_t size_type;
     248             : 
     249             :   typedef StringMapConstIterator<ValueTy> const_iterator;
     250             :   typedef StringMapIterator<ValueTy> iterator;
     251             : 
     252             :   iterator begin() {
     253             :     return iterator(TheTable, NumBuckets == 0);
     254             :   }
     255             :   iterator end() {
     256             :     return iterator(TheTable+NumBuckets, true);
     257             :   }
     258             :   const_iterator begin() const {
     259             :     return const_iterator(TheTable, NumBuckets == 0);
     260             :   }
     261             :   const_iterator end() const {
     262             :     return const_iterator(TheTable+NumBuckets, true);
     263             :   }
     264             : 
     265             :   iterator find(StringRef Key) {
     266             :     int Bucket = FindKey(Key);
     267             :     if (Bucket == -1) return end();
     268             :     return iterator(TheTable+Bucket, true);
     269             :   }
     270             : 
     271             :   const_iterator find(StringRef Key) const {
     272             :     int Bucket = FindKey(Key);
     273             :     if (Bucket == -1) return end();
     274             :     return const_iterator(TheTable+Bucket, true);
     275             :   }
     276             : 
     277             :   /// lookup - Return the entry for the specified key, or a default
     278             :   /// constructed value if no such entry exists.
     279             :   ValueTy lookup(StringRef Key) const {
     280             :     const_iterator it = find(Key);
     281             :     if (it != end())
     282             :       return it->second;
     283             :     return ValueTy();
     284             :   }
     285             : 
     286             :   ValueTy &operator[](StringRef Key) {
     287             :     return insert(std::make_pair(Key, ValueTy())).first->second;
     288             :   }
     289             : 
     290             :   /// count - Return 1 if the element is in the map, 0 otherwise.
     291             :   size_type count(StringRef Key) const {
     292             :     return find(Key) == end() ? 0 : 1;
     293             :   }
     294             : 
     295             :   /// insert - Insert the specified key/value pair into the map.  If the key
     296             :   /// already exists in the map, return false and ignore the request, otherwise
     297             :   /// insert it and return true.
     298             :   bool insert(MapEntryTy *KeyValue) {
     299             :     unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
     300             :     StringMapEntryBase *&Bucket = TheTable[BucketNo];
     301             :     if (Bucket && Bucket != getTombstoneVal())
     302             :       return false;  // Already exists in map.
     303             : 
     304             :     if (Bucket == getTombstoneVal())
     305             :       --NumTombstones;
     306             :     Bucket = KeyValue;
     307             :     ++NumItems;
     308             :     assert(NumItems + NumTombstones <= NumBuckets);
     309             : 
     310             :     RehashTable();
     311             :     return true;
     312             :   }
     313             : 
     314             :   /// insert - Inserts the specified key/value pair into the map if the key
     315             :   /// isn't already in the map. The bool component of the returned pair is true
     316             :   /// if and only if the insertion takes place, and the iterator component of
     317             :   /// the pair points to the element with key equivalent to the key of the pair.
     318             :   std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
     319             :     unsigned BucketNo = LookupBucketFor(KV.first);
     320             :     StringMapEntryBase *&Bucket = TheTable[BucketNo];
     321             :     if (Bucket && Bucket != getTombstoneVal())
     322             :       return std::make_pair(iterator(TheTable + BucketNo, false),
     323             :                             false); // Already exists in map.
     324             : 
     325             :     if (Bucket == getTombstoneVal())
     326             :       --NumTombstones;
     327             :     Bucket =
     328             :         MapEntryTy::Create(KV.first, Allocator, std::move(KV.second));
     329             :     ++NumItems;
     330             :     assert(NumItems + NumTombstones <= NumBuckets);
     331             : 
     332             :     BucketNo = RehashTable(BucketNo);
     333             :     return std::make_pair(iterator(TheTable + BucketNo, false), true);
     334             :   }
     335             : 
     336             :   // clear - Empties out the StringMap
     337             :   void clear() {
     338             :     if (empty()) return;
     339             : 
     340             :     // Zap all values, resetting the keys back to non-present (not tombstone),
     341             :     // which is safe because we're removing all elements.
     342             :     for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
     343             :       StringMapEntryBase *&Bucket = TheTable[I];
     344             :       if (Bucket && Bucket != getTombstoneVal()) {
     345             :         static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
     346             :       }
     347             :       Bucket = nullptr;
     348             :     }
     349             : 
     350             :     NumItems = 0;
     351             :     NumTombstones = 0;
     352             :   }
     353             : 
     354             :   /// remove - Remove the specified key/value pair from the map, but do not
     355             :   /// erase it.  This aborts if the key is not in the map.
     356             :   void remove(MapEntryTy *KeyValue) {
     357             :     RemoveKey(KeyValue);
     358             :   }
     359             : 
     360             :   void erase(iterator I) {
     361             :     MapEntryTy &V = *I;
     362             :     remove(&V);
     363             :     V.Destroy(Allocator);
     364             :   }
     365             : 
     366             :   bool erase(StringRef Key) {
     367             :     iterator I = find(Key);
     368             :     if (I == end()) return false;
     369             :     erase(I);
     370             :     return true;
     371             :   }
     372             : 
     373             :   ~StringMap() {
     374             :     // Delete all the elements in the map, but don't reset the elements
     375             :     // to default values.  This is a copy of clear(), but avoids unnecessary
     376             :     // work not required in the destructor.
     377          48 :     if (!empty()) {
     378         816 :       for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
     379         384 :         StringMapEntryBase *Bucket = TheTable[I];
     380         432 :         if (Bucket && Bucket != getTombstoneVal()) {
     381          24 :           static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
     382          24 :         }
     383         384 :       }
     384          24 :     }
     385          24 :     free(TheTable);
     386          24 :   }
     387             : };
     388             : 
     389             : 
     390             : template<typename ValueTy>
     391             : class StringMapConstIterator {
     392             : protected:
     393             :   StringMapEntryBase **Ptr;
     394             : public:
     395             :   typedef StringMapEntry<ValueTy> value_type;
     396             : 
     397             :   StringMapConstIterator() : Ptr(nullptr) { }
     398             : 
     399             :   explicit StringMapConstIterator(StringMapEntryBase **Bucket,
     400             :                                   bool NoAdvance = false)
     401             :   : Ptr(Bucket) {
     402             :     if (!NoAdvance) AdvancePastEmptyBuckets();
     403             :   }
     404             : 
     405             :   const value_type &operator*() const {
     406             :     return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
     407             :   }
     408             :   const value_type *operator->() const {
     409             :     return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
     410             :   }
     411             : 
     412             :   bool operator==(const StringMapConstIterator &RHS) const {
     413             :     return Ptr == RHS.Ptr;
     414             :   }
     415             :   bool operator!=(const StringMapConstIterator &RHS) const {
     416             :     return Ptr != RHS.Ptr;
     417             :   }
     418             : 
     419             :   inline StringMapConstIterator& operator++() {   // Preincrement
     420             :     ++Ptr;
     421             :     AdvancePastEmptyBuckets();
     422             :     return *this;
     423             :   }
     424             :   StringMapConstIterator operator++(int) {        // Postincrement
     425             :     StringMapConstIterator tmp = *this; ++*this; return tmp;
     426             :   }
     427             : 
     428             : private:
     429             :   void AdvancePastEmptyBuckets() {
     430             :     while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
     431             :       ++Ptr;
     432             :   }
     433             : };
     434             : 
     435             : template<typename ValueTy>
     436             : class StringMapIterator : public StringMapConstIterator<ValueTy> {
     437             : public:
     438             :   StringMapIterator() {}
     439             :   explicit StringMapIterator(StringMapEntryBase **Bucket,
     440             :                              bool NoAdvance = false)
     441             :     : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
     442             :   }
     443             :   StringMapEntry<ValueTy> &operator*() const {
     444             :     return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
     445             :   }
     446             :   StringMapEntry<ValueTy> *operator->() const {
     447             :     return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
     448             :   }
     449             : };
     450             : 
     451             : }
     452             : 
     453             : #endif

Generated by: LCOV version 1.11