StringMap.h revision 23d7b3611759c7fb3a853dfce3ee3d43ef5ca67d
1//===--- CStringMap.h - CString Hash table map interface --------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Chris Lattner and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the CStringMap class. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_ADT_CSTRINGMAP_H 15#define LLVM_ADT_CSTRINGMAP_H 16 17#include "llvm/Support/Allocator.h" 18#include <cstring> 19 20namespace llvm { 21 22/// CStringMapVisitor - Subclasses of this class may be implemented to walk all 23/// of the items in a CStringMap. 24class CStringMapVisitor { 25public: 26 virtual ~CStringMapVisitor(); 27 virtual void Visit(const char *Key, void *Value) const = 0; 28}; 29 30/// CStringMapImpl - This is the base class of CStringMap that is shared among 31/// all of its instantiations. 32class CStringMapImpl { 33protected: 34 /// ItemBucket - The hash table consists of an array of these. If Item is 35 /// non-null, this is an extant entry, otherwise, it is a hole. 36 struct ItemBucket { 37 /// FullHashValue - This remembers the full hash value of the key for 38 /// easy scanning. 39 unsigned FullHashValue; 40 41 /// Item - This is a pointer to the actual item object. 42 void *Item; 43 }; 44 45 ItemBucket *TheTable; 46 unsigned NumBuckets; 47 unsigned NumItems; 48 unsigned ItemSize; 49protected: 50 CStringMapImpl(unsigned InitSize, unsigned ItemSize); 51 void RehashTable(); 52 53 /// LookupBucketFor - Look up the bucket that the specified string should end 54 /// up in. If it already exists as a key in the map, the Item pointer for the 55 /// specified bucket will be non-null. Otherwise, it will be null. In either 56 /// case, the FullHashValue field of the bucket will be set to the hash value 57 /// of the string. 58 unsigned LookupBucketFor(const char *KeyStart, const char *KeyEnd); 59 60public: 61 unsigned getNumBuckets() const { return NumBuckets; } 62 unsigned getNumItems() const { return NumItems; } 63 64 void VisitEntries(const CStringMapVisitor &Visitor) const; 65}; 66 67 68/// CStringMap - This is an unconventional map that is specialized for handling 69/// keys that are "C strings", that is, null-terminated strings. This does some 70/// funky memory allocation and hashing things to make it extremely efficient, 71/// storing the string data *after* the value in the map. 72template<typename ValueTy, typename AllocatorTy = MallocAllocator> 73class CStringMap : public CStringMapImpl { 74 AllocatorTy Allocator; 75public: 76 CStringMap(unsigned InitialSize = 0) 77 : CStringMapImpl(InitialSize, sizeof(ValueTy)) {} 78 79 AllocatorTy &getAllocator() { return Allocator; } 80 const AllocatorTy &getAllocator() const { return Allocator; } 81 82 /// FindValue - Look up the specified key in the map. If it exists, return a 83 /// pointer to the element, otherwise return null. 84 ValueTy *FindValue(const char *KeyStart, const char *KeyEnd) { 85 unsigned BucketNo = LookupBucketFor(KeyStart, KeyEnd); 86 return static_cast<ValueTy*>(TheTable[BucketNo].Item); 87 } 88 89 /// GetOrCreateValue - Look up the specified key in the table. If a value 90 /// exists, return it. Otherwise, default construct a value, insert it, and 91 /// return. 92 ValueTy &GetOrCreateValue(const char *KeyStart, const char *KeyEnd) { 93 unsigned BucketNo = LookupBucketFor(KeyStart, KeyEnd); 94 ItemBucket &Bucket = TheTable[BucketNo]; 95 if (Bucket.Item) 96 return *static_cast<ValueTy*>(Bucket.Item); 97 98 unsigned KeyLength = KeyEnd-KeyStart; 99 100 // Okay, the item doesn't already exist, and Bucket is the bucket to fill 101 // in. Allocate a new item with space for the null-terminated string at the 102 // end. 103 unsigned AllocSize = sizeof(ValueTy)+KeyLength+1; 104 105#ifdef __GNUC__ 106 unsigned Alignment = __alignof__(ValueTy); 107#else 108 // FIXME: ugly. 109 unsigned Alignment = 8; 110#endif 111 ValueTy *NewItem = (ValueTy*)Allocator.Allocate(AllocSize, Alignment); 112 new (NewItem) ValueTy(); 113 ++NumItems; 114 115 // Copy the string information. 116 char *StrBuffer = (char*)(NewItem+1); 117 memcpy(StrBuffer, KeyStart, KeyLength); 118 StrBuffer[KeyLength] = 0; // Null terminate string. 119 120 // Fill in the bucket for the hash table. The FullHashValue was already 121 // filled in by LookupBucketFor. 122 Bucket.Item = NewItem; 123 124 // If the hash table is now more than 3/4 full, rehash into a larger table. 125 if (NumItems > NumBuckets*3/4) 126 RehashTable(); 127 return *NewItem; 128 } 129 130 ~CStringMap() { 131 for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) { 132 if (ValueTy *Id = static_cast<ValueTy*>(I->Item)) { 133 // Free memory referenced by the item. 134 Id->~ValueTy(); 135 Allocator.Deallocate(Id); 136 } 137 } 138 delete [] TheTable; 139 } 140}; 141 142} 143 144#endif