1198090Srdivacky//===-- StringPool.h - Interned string pool ---------------------*- C++ -*-===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file declares an interned string pool, which helps reduce the cost of 11193323Sed// strings by using the same storage for identical strings. 12193323Sed// 13193323Sed// To intern a string: 14193323Sed// 15193323Sed// StringPool Pool; 16193323Sed// PooledStringPtr Str = Pool.intern("wakka wakka"); 17193323Sed// 18193323Sed// To use the value of an interned string, use operator bool and operator*: 19193323Sed// 20193323Sed// if (Str) 21193323Sed// cerr << "the string is" << *Str << "\n"; 22193323Sed// 23193323Sed// Pooled strings are immutable, but you can change a PooledStringPtr to point 24193323Sed// to another instance. So that interned strings can eventually be freed, 25193323Sed// strings in the string pool are reference-counted (automatically). 26193323Sed// 27193323Sed//===----------------------------------------------------------------------===// 28193323Sed 29193323Sed#ifndef LLVM_SUPPORT_STRINGPOOL_H 30193323Sed#define LLVM_SUPPORT_STRINGPOOL_H 31193323Sed 32193323Sed#include "llvm/ADT/StringMap.h" 33249423Sdim#include <cassert> 34193323Sed#include <new> 35193323Sed 36193323Sednamespace llvm { 37193323Sed 38193323Sed class PooledStringPtr; 39193323Sed 40193323Sed /// StringPool - An interned string pool. Use the intern method to add a 41193323Sed /// string. Strings are removed automatically as PooledStringPtrs are 42193323Sed /// destroyed. 43193323Sed class StringPool { 44193323Sed /// PooledString - This is the value of an entry in the pool's interning 45193323Sed /// table. 46193323Sed struct PooledString { 47193323Sed StringPool *Pool; ///< So the string can remove itself. 48193323Sed unsigned Refcount; ///< Number of referencing PooledStringPtrs. 49193323Sed 50193323Sed public: 51193323Sed PooledString() : Pool(0), Refcount(0) { } 52193323Sed }; 53193323Sed 54193323Sed friend class PooledStringPtr; 55193323Sed 56193323Sed typedef StringMap<PooledString> table_t; 57193323Sed typedef StringMapEntry<PooledString> entry_t; 58193323Sed table_t InternTable; 59193323Sed 60193323Sed public: 61193323Sed StringPool(); 62193323Sed ~StringPool(); 63193323Sed 64193323Sed /// intern - Adds a string to the pool and returns a reference-counted 65193323Sed /// pointer to it. No additional memory is allocated if the string already 66193323Sed /// exists in the pool. 67210299Sed PooledStringPtr intern(StringRef Str); 68193323Sed 69193323Sed /// empty - Checks whether the pool is empty. Returns true if so. 70193323Sed /// 71193323Sed inline bool empty() const { return InternTable.empty(); } 72193323Sed }; 73193323Sed 74193323Sed /// PooledStringPtr - A pointer to an interned string. Use operator bool to 75193323Sed /// test whether the pointer is valid, and operator * to get the string if so. 76193323Sed /// This is a lightweight value class with storage requirements equivalent to 77193323Sed /// a single pointer, but it does have reference-counting overhead when 78193323Sed /// copied. 79193323Sed class PooledStringPtr { 80193323Sed typedef StringPool::entry_t entry_t; 81193323Sed entry_t *S; 82193323Sed 83193323Sed public: 84193323Sed PooledStringPtr() : S(0) {} 85193323Sed 86193323Sed explicit PooledStringPtr(entry_t *E) : S(E) { 87193323Sed if (S) ++S->getValue().Refcount; 88193323Sed } 89193323Sed 90193323Sed PooledStringPtr(const PooledStringPtr &That) : S(That.S) { 91193323Sed if (S) ++S->getValue().Refcount; 92193323Sed } 93193323Sed 94193323Sed PooledStringPtr &operator=(const PooledStringPtr &That) { 95193323Sed if (S != That.S) { 96193323Sed clear(); 97193323Sed S = That.S; 98193323Sed if (S) ++S->getValue().Refcount; 99193323Sed } 100193323Sed return *this; 101193323Sed } 102193323Sed 103193323Sed void clear() { 104193323Sed if (!S) 105193323Sed return; 106193323Sed if (--S->getValue().Refcount == 0) { 107193323Sed S->getValue().Pool->InternTable.remove(S); 108193323Sed S->Destroy(); 109193323Sed } 110193323Sed S = 0; 111193323Sed } 112193323Sed 113193323Sed ~PooledStringPtr() { clear(); } 114193323Sed 115193323Sed inline const char *begin() const { 116193323Sed assert(*this && "Attempt to dereference empty PooledStringPtr!"); 117193323Sed return S->getKeyData(); 118193323Sed } 119193323Sed 120193323Sed inline const char *end() const { 121193323Sed assert(*this && "Attempt to dereference empty PooledStringPtr!"); 122193323Sed return S->getKeyData() + S->getKeyLength(); 123193323Sed } 124193323Sed 125193323Sed inline unsigned size() const { 126193323Sed assert(*this && "Attempt to dereference empty PooledStringPtr!"); 127193323Sed return S->getKeyLength(); 128193323Sed } 129193323Sed 130193323Sed inline const char *operator*() const { return begin(); } 131193323Sed inline operator bool() const { return S != 0; } 132193323Sed 133193323Sed inline bool operator==(const PooledStringPtr &That) { return S == That.S; } 134193323Sed inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } 135193323Sed }; 136193323Sed 137193323Sed} // End llvm namespace 138193323Sed 139193323Sed#endif 140