00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00032 template<typename ValueTy>
00033 class StringMapEntryInitializer {
00034 public:
00035 template <typename InitTy>
00036 static void Initialize(StringMapEntry<ValueTy> &T, InitTy InitVal) {
00037 T.second = InitVal;
00038 }
00039 };
00040
00041
00043 class StringMapEntryBase {
00044 unsigned StrLen;
00045 public:
00046 explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
00047
00048 unsigned getKeyLength() const { return StrLen; }
00049 };
00050
00053 class StringMapImpl {
00054 public:
00057 struct ItemBucket {
00060 unsigned FullHashValue;
00061
00063 StringMapEntryBase *Item;
00064 };
00065
00066 protected:
00067 ItemBucket *TheTable;
00068 unsigned NumBuckets;
00069 unsigned NumItems;
00070 unsigned NumTombstones;
00071 unsigned ItemSize;
00072 protected:
00073 explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) {
00074
00075 TheTable = 0;
00076 NumBuckets = 0;
00077 NumItems = 0;
00078 NumTombstones = 0;
00079 }
00080 StringMapImpl(unsigned InitSize, unsigned ItemSize);
00081 void RehashTable();
00082
00088 unsigned LookupBucketFor(StringRef Key);
00089
00093 int FindKey(StringRef Key) const;
00094
00097 void RemoveKey(StringMapEntryBase *V);
00098
00101 StringMapEntryBase *RemoveKey(StringRef Key);
00102 private:
00103 void init(unsigned Size);
00104 public:
00105 static StringMapEntryBase *getTombstoneVal() {
00106 return (StringMapEntryBase*)-1;
00107 }
00108
00109 unsigned getNumBuckets() const { return NumBuckets; }
00110 unsigned getNumItems() const { return NumItems; }
00111
00112 bool empty() const { return NumItems == 0; }
00113 unsigned size() const { return NumItems; }
00114 };
00115
00119 template<typename ValueTy>
00120 class StringMapEntry : public StringMapEntryBase {
00121 public:
00122 ValueTy second;
00123
00124 explicit StringMapEntry(unsigned strLen)
00125 : StringMapEntryBase(strLen), second() {}
00126 StringMapEntry(unsigned strLen, const ValueTy &V)
00127 : StringMapEntryBase(strLen), second(V) {}
00128
00129 StringRef getKey() const {
00130 return StringRef(getKeyData(), getKeyLength());
00131 }
00132
00133 const ValueTy &getValue() const { return second; }
00134 ValueTy &getValue() { return second; }
00135
00136 void setValue(const ValueTy &V) { second = V; }
00137
00141 const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
00142
00143 StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
00144
00147 template<typename AllocatorTy, typename InitType>
00148 static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
00149 AllocatorTy &Allocator,
00150 InitType InitVal) {
00151 unsigned KeyLength = static_cast<unsigned>(KeyEnd-KeyStart);
00152
00153
00154
00155
00156
00157 unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
00158 KeyLength+1;
00159 unsigned Alignment = alignOf<StringMapEntry>();
00160
00161 StringMapEntry *NewItem =
00162 static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
00163
00164
00165 new (NewItem) StringMapEntry(KeyLength);
00166
00167
00168 char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
00169 memcpy(StrBuffer, KeyStart, KeyLength);
00170 StrBuffer[KeyLength] = 0;
00171
00172
00173 StringMapEntryInitializer<ValueTy>::Initialize(*NewItem, InitVal);
00174 return NewItem;
00175 }
00176
00177 template<typename AllocatorTy>
00178 static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
00179 AllocatorTy &Allocator) {
00180 return Create(KeyStart, KeyEnd, Allocator, 0);
00181 }
00182
00183
00185 template<typename InitType>
00186 static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
00187 InitType InitVal) {
00188 MallocAllocator A;
00189 return Create(KeyStart, KeyEnd, A, InitVal);
00190 }
00191
00192 static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) {
00193 return Create(KeyStart, KeyEnd, ValueTy());
00194 }
00195
00198 static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) {
00199 StringMapEntry *EPtr = 0;
00200 char *Ptr = reinterpret_cast<char*>(&V) -
00201 (reinterpret_cast<char*>(&EPtr->second) -
00202 reinterpret_cast<char*>(EPtr));
00203 return *reinterpret_cast<StringMapEntry*>(Ptr);
00204 }
00205 static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) {
00206 return GetStringMapEntryFromValue(const_cast<ValueTy&>(V));
00207 }
00208
00211 static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
00212 char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
00213 return *reinterpret_cast<StringMapEntry*>(Ptr);
00214 }
00215
00216
00219 template<typename AllocatorTy>
00220 void Destroy(AllocatorTy &Allocator) {
00221
00222 this->~StringMapEntry();
00223 Allocator.Deallocate(this);
00224 }
00225
00227 void Destroy() {
00228 MallocAllocator A;
00229 Destroy(A);
00230 }
00231 };
00232
00233
00238 template<typename ValueTy, typename AllocatorTy = MallocAllocator>
00239 class StringMap : public StringMapImpl {
00240 AllocatorTy Allocator;
00241 typedef StringMapEntry<ValueTy> MapEntryTy;
00242 public:
00243 StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
00244 explicit StringMap(unsigned InitialSize)
00245 : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
00246
00247 explicit StringMap(AllocatorTy A)
00248 : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
00249
00250 explicit StringMap(const StringMap &RHS)
00251 : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
00252 assert(RHS.empty() &&
00253 "Copy ctor from non-empty stringmap not implemented yet!");
00254 (void)RHS;
00255 }
00256 void operator=(const StringMap &RHS) {
00257 assert(RHS.empty() &&
00258 "assignment from non-empty stringmap not implemented yet!");
00259 (void)RHS;
00260 clear();
00261 }
00262
00263 typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
00264 typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
00265 AllocatorRefTy getAllocator() { return Allocator; }
00266 AllocatorCRefTy getAllocator() const { return Allocator; }
00267
00268 typedef const char* key_type;
00269 typedef ValueTy mapped_type;
00270 typedef StringMapEntry<ValueTy> value_type;
00271 typedef size_t size_type;
00272
00273 typedef StringMapConstIterator<ValueTy> const_iterator;
00274 typedef StringMapIterator<ValueTy> iterator;
00275
00276 iterator begin() {
00277 return iterator(TheTable, NumBuckets == 0);
00278 }
00279 iterator end() {
00280 return iterator(TheTable+NumBuckets, true);
00281 }
00282 const_iterator begin() const {
00283 return const_iterator(TheTable, NumBuckets == 0);
00284 }
00285 const_iterator end() const {
00286 return const_iterator(TheTable+NumBuckets, true);
00287 }
00288
00289 iterator find(StringRef Key) {
00290 int Bucket = FindKey(Key);
00291 if (Bucket == -1) return end();
00292 return iterator(TheTable+Bucket);
00293 }
00294
00295 const_iterator find(StringRef Key) const {
00296 int Bucket = FindKey(Key);
00297 if (Bucket == -1) return end();
00298 return const_iterator(TheTable+Bucket);
00299 }
00300
00303 ValueTy lookup(StringRef Key) const {
00304 const_iterator it = find(Key);
00305 if (it != end())
00306 return it->second;
00307 return ValueTy();
00308 }
00309
00310 ValueTy &operator[](StringRef Key) {
00311 return GetOrCreateValue(Key).getValue();
00312 }
00313
00314 size_type count(StringRef Key) const {
00315 return find(Key) == end() ? 0 : 1;
00316 }
00317
00321 bool insert(MapEntryTy *KeyValue) {
00322 unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
00323 ItemBucket &Bucket = TheTable[BucketNo];
00324 if (Bucket.Item && Bucket.Item != getTombstoneVal())
00325 return false;
00326
00327 if (Bucket.Item == getTombstoneVal())
00328 --NumTombstones;
00329 Bucket.Item = KeyValue;
00330 ++NumItems;
00331 assert(NumItems + NumTombstones <= NumBuckets);
00332
00333 RehashTable();
00334 return true;
00335 }
00336
00337
00338 void clear() {
00339 if (empty()) return;
00340
00341
00342
00343 for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) {
00344 if (I->Item && I->Item != getTombstoneVal()) {
00345 static_cast<MapEntryTy*>(I->Item)->Destroy(Allocator);
00346 I->Item = 0;
00347 }
00348 }
00349
00350 NumItems = 0;
00351 NumTombstones = 0;
00352 }
00353
00357 template <typename InitTy>
00358 MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
00359 unsigned BucketNo = LookupBucketFor(Key);
00360 ItemBucket &Bucket = TheTable[BucketNo];
00361 if (Bucket.Item && Bucket.Item != getTombstoneVal())
00362 return *static_cast<MapEntryTy*>(Bucket.Item);
00363
00364 MapEntryTy *NewItem =
00365 MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val);
00366
00367 if (Bucket.Item == getTombstoneVal())
00368 --NumTombstones;
00369 ++NumItems;
00370 assert(NumItems + NumTombstones <= NumBuckets);
00371
00372
00373
00374 Bucket.Item = NewItem;
00375
00376 RehashTable();
00377 return *NewItem;
00378 }
00379
00380 MapEntryTy &GetOrCreateValue(StringRef Key) {
00381 return GetOrCreateValue(Key, ValueTy());
00382 }
00383
00386 void remove(MapEntryTy *KeyValue) {
00387 RemoveKey(KeyValue);
00388 }
00389
00390 void erase(iterator I) {
00391 MapEntryTy &V = *I;
00392 remove(&V);
00393 V.Destroy(Allocator);
00394 }
00395
00396 bool erase(StringRef Key) {
00397 iterator I = find(Key);
00398 if (I == end()) return false;
00399 erase(I);
00400 return true;
00401 }
00402
00403 ~StringMap() {
00404 clear();
00405 free(TheTable);
00406 }
00407 };
00408
00409
00410 template<typename ValueTy>
00411 class StringMapConstIterator {
00412 protected:
00413 StringMapImpl::ItemBucket *Ptr;
00414 public:
00415 typedef StringMapEntry<ValueTy> value_type;
00416
00417 explicit StringMapConstIterator(StringMapImpl::ItemBucket *Bucket,
00418 bool NoAdvance = false)
00419 : Ptr(Bucket) {
00420 if (!NoAdvance) AdvancePastEmptyBuckets();
00421 }
00422
00423 const value_type &operator*() const {
00424 return *static_cast<StringMapEntry<ValueTy>*>(Ptr->Item);
00425 }
00426 const value_type *operator->() const {
00427 return static_cast<StringMapEntry<ValueTy>*>(Ptr->Item);
00428 }
00429
00430 bool operator==(const StringMapConstIterator &RHS) const {
00431 return Ptr == RHS.Ptr;
00432 }
00433 bool operator!=(const StringMapConstIterator &RHS) const {
00434 return Ptr != RHS.Ptr;
00435 }
00436
00437 inline StringMapConstIterator& operator++() {
00438 ++Ptr;
00439 AdvancePastEmptyBuckets();
00440 return *this;
00441 }
00442 StringMapConstIterator operator++(int) {
00443 StringMapConstIterator tmp = *this; ++*this; return tmp;
00444 }
00445
00446 private:
00447 void AdvancePastEmptyBuckets() {
00448 while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal())
00449 ++Ptr;
00450 }
00451 };
00452
00453 template<typename ValueTy>
00454 class StringMapIterator : public StringMapConstIterator<ValueTy> {
00455 public:
00456 explicit StringMapIterator(StringMapImpl::ItemBucket *Bucket,
00457 bool NoAdvance = false)
00458 : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
00459 }
00460 StringMapEntry<ValueTy> &operator*() const {
00461 return *static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item);
00462 }
00463 StringMapEntry<ValueTy> *operator->() const {
00464 return static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item);
00465 }
00466 };
00467
00468 }
00469
00470 #endif