StringPool.h revision 208954
1249261Sdim//===-- StringPool.h - Interned string pool ---------------------*- C++ -*-===// 2249261Sdim// 3353358Sdim// The LLVM Compiler Infrastructure 4353358Sdim// 5353358Sdim// This file is distributed under the University of Illinois Open Source 6249261Sdim// License. See LICENSE.TXT for details. 7249261Sdim// 8249261Sdim//===----------------------------------------------------------------------===// 9341825Sdim// 10249261Sdim// This file declares an interned string pool, which helps reduce the cost of 11249261Sdim// strings by using the same storage for identical strings. 12249261Sdim// 13276479Sdim// To intern a string: 14261991Sdim// 15261991Sdim// StringPool Pool; 16249261Sdim// PooledStringPtr Str = Pool.intern("wakka wakka"); 17321369Sdim// 18261991Sdim// To use the value of an interned string, use operator bool and operator*: 19261991Sdim// 20296417Sdim// if (Str) 21249261Sdim// cerr << "the string is" << *Str << "\n"; 22249261Sdim// 23249261Sdim// Pooled strings are immutable, but you can change a PooledStringPtr to point 24249261Sdim// to another instance. So that interned strings can eventually be freed, 25249261Sdim// strings in the string pool are reference-counted (automatically). 26249261Sdim// 27309124Sdim//===----------------------------------------------------------------------===// 28309124Sdim 29309124Sdim#ifndef LLVM_SUPPORT_STRINGPOOL_H 30309124Sdim#define LLVM_SUPPORT_STRINGPOOL_H 31309124Sdim 32309124Sdim#include "llvm/ADT/StringMap.h" 33309124Sdim#include <new> 34309124Sdim#include <cassert> 35309124Sdim 36309124Sdimnamespace llvm { 37309124Sdim 38309124Sdim class PooledStringPtr; 39309124Sdim 40309124Sdim /// StringPool - An interned string pool. Use the intern method to add a 41314564Sdim /// string. Strings are removed automatically as PooledStringPtrs are 42314564Sdim /// destroyed. 43353358Sdim class StringPool { 44353358Sdim /// PooledString - This is the value of an entry in the pool's interning 45309124Sdim /// table. 46309124Sdim struct PooledString { 47353358Sdim StringPool *Pool; ///< So the string can remove itself. 48309124Sdim unsigned Refcount; ///< Number of referencing PooledStringPtrs. 49309124Sdim 50353358Sdim public: 51309124Sdim PooledString() : Pool(0), Refcount(0) { } 52309124Sdim }; 53353358Sdim 54353358Sdim friend class PooledStringPtr; 55309124Sdim 56353358Sdim typedef StringMap<PooledString> table_t; 57353358Sdim typedef StringMapEntry<PooledString> entry_t; 58309124Sdim table_t InternTable; 59309124Sdim 60309124Sdim public: 61309124Sdim StringPool(); 62309124Sdim ~StringPool(); 63309124Sdim 64309124Sdim /// intern - Adds a string to the pool and returns a reference-counted 65309124Sdim /// pointer to it. No additional memory is allocated if the string already 66309124Sdim /// exists in the pool. 67309124Sdim PooledStringPtr intern(const StringRef &Str); 68309124Sdim 69309124Sdim /// empty - Checks whether the pool is empty. Returns true if so. 70309124Sdim /// 71309124Sdim inline bool empty() const { return InternTable.empty(); } 72309124Sdim }; 73309124Sdim 74309124Sdim /// PooledStringPtr - A pointer to an interned string. Use operator bool to 75309124Sdim /// test whether the pointer is valid, and operator * to get the string if so. 76309124Sdim /// This is a lightweight value class with storage requirements equivalent to 77309124Sdim /// a single pointer, but it does have reference-counting overhead when 78309124Sdim /// copied. 79309124Sdim class PooledStringPtr { 80309124Sdim typedef StringPool::entry_t entry_t; 81309124Sdim entry_t *S; 82353358Sdim 83309124Sdim public: 84309124Sdim PooledStringPtr() : S(0) {} 85309124Sdim 86341825Sdim explicit PooledStringPtr(entry_t *E) : S(E) { 87280031Sdim if (S) ++S->getValue().Refcount; 88280031Sdim } 89280031Sdim 90309124Sdim PooledStringPtr(const PooledStringPtr &That) : S(That.S) { 91341825Sdim if (S) ++S->getValue().Refcount; 92341825Sdim } 93353358Sdim 94341825Sdim PooledStringPtr &operator=(const PooledStringPtr &That) { 95341825Sdim if (S != That.S) { 96341825Sdim clear(); 97341825Sdim S = That.S; 98341825Sdim if (S) ++S->getValue().Refcount; 99341825Sdim } 100341825Sdim return *this; 101341825Sdim } 102341825Sdim 103341825Sdim void clear() { 104341825Sdim if (!S) 105341825Sdim return; 106341825Sdim if (--S->getValue().Refcount == 0) { 107341825Sdim S->getValue().Pool->InternTable.remove(S); 108341825Sdim S->Destroy(); 109341825Sdim } 110341825Sdim S = 0; 111341825Sdim } 112341825Sdim 113341825Sdim ~PooledStringPtr() { clear(); } 114341825Sdim 115341825Sdim inline const char *begin() const { 116341825Sdim assert(*this && "Attempt to dereference empty PooledStringPtr!"); 117341825Sdim return S->getKeyData(); 118341825Sdim } 119341825Sdim 120341825Sdim inline const char *end() const { 121341825Sdim assert(*this && "Attempt to dereference empty PooledStringPtr!"); 122341825Sdim return S->getKeyData() + S->getKeyLength(); 123341825Sdim } 124341825Sdim 125341825Sdim inline unsigned size() const { 126341825Sdim assert(*this && "Attempt to dereference empty PooledStringPtr!"); 127341825Sdim return S->getKeyLength(); 128341825Sdim } 129341825Sdim 130341825Sdim inline const char *operator*() const { return begin(); } 131341825Sdim inline operator bool() const { return S != 0; } 132341825Sdim 133341825Sdim inline bool operator==(const PooledStringPtr &That) { return S == That.S; } 134341825Sdim inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } 135309124Sdim }; 136341825Sdim 137309124Sdim} // End llvm namespace 138276479Sdim 139309124Sdim#endif 140309124Sdim