StringPool.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //===-- StringPool.h - Interned string pool ---------------------*- 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 declares an interned string pool, which helps reduce the cost of
  11. // strings by using the same storage for identical strings.
  12. //
  13. // To intern a string:
  14. //
  15. // StringPool Pool;
  16. // PooledStringPtr Str = Pool.intern("wakka wakka");
  17. //
  18. // To use the value of an interned string, use operator bool and operator*:
  19. //
  20. // if (Str)
  21. // cerr << "the string is" << *Str << "\n";
  22. //
  23. // Pooled strings are immutable, but you can change a PooledStringPtr to point
  24. // to another instance. So that interned strings can eventually be freed,
  25. // strings in the string pool are reference-counted (automatically).
  26. //
  27. //===----------------------------------------------------------------------===//
  28. #ifndef LLVM_SUPPORT_STRINGPOOL_H
  29. #define LLVM_SUPPORT_STRINGPOOL_H
  30. #include "llvm/ADT/StringMap.h"
  31. #include <cassert>
  32. namespace llvm {
  33. class PooledStringPtr;
  34. /// StringPool - An interned string pool. Use the intern method to add a
  35. /// string. Strings are removed automatically as PooledStringPtrs are
  36. /// destroyed.
  37. class StringPool {
  38. /// PooledString - This is the value of an entry in the pool's interning
  39. /// table.
  40. struct PooledString {
  41. StringPool *Pool; ///< So the string can remove itself.
  42. unsigned Refcount; ///< Number of referencing PooledStringPtrs.
  43. public:
  44. PooledString() : Pool(nullptr), Refcount(0) { }
  45. };
  46. friend class PooledStringPtr;
  47. typedef StringMap<PooledString> table_t;
  48. typedef StringMapEntry<PooledString> entry_t;
  49. table_t InternTable;
  50. public:
  51. StringPool();
  52. ~StringPool();
  53. /// intern - Adds a string to the pool and returns a reference-counted
  54. /// pointer to it. No additional memory is allocated if the string already
  55. /// exists in the pool.
  56. PooledStringPtr intern(StringRef Str);
  57. /// empty - Checks whether the pool is empty. Returns true if so.
  58. ///
  59. inline bool empty() const { return InternTable.empty(); }
  60. };
  61. /// PooledStringPtr - A pointer to an interned string. Use operator bool to
  62. /// test whether the pointer is valid, and operator * to get the string if so.
  63. /// This is a lightweight value class with storage requirements equivalent to
  64. /// a single pointer, but it does have reference-counting overhead when
  65. /// copied.
  66. class PooledStringPtr {
  67. typedef StringPool::entry_t entry_t;
  68. entry_t *S;
  69. public:
  70. PooledStringPtr() : S(nullptr) {}
  71. explicit PooledStringPtr(entry_t *E) : S(E) {
  72. if (S) ++S->getValue().Refcount;
  73. }
  74. PooledStringPtr(const PooledStringPtr &That) : S(That.S) {
  75. if (S) ++S->getValue().Refcount;
  76. }
  77. PooledStringPtr &operator=(const PooledStringPtr &That) {
  78. if (S != That.S) {
  79. clear();
  80. S = That.S;
  81. if (S) ++S->getValue().Refcount;
  82. }
  83. return *this;
  84. }
  85. void clear() {
  86. if (!S)
  87. return;
  88. if (--S->getValue().Refcount == 0) {
  89. S->getValue().Pool->InternTable.remove(S);
  90. S->Destroy();
  91. }
  92. S = nullptr;
  93. }
  94. ~PooledStringPtr() { clear(); }
  95. inline const char *begin() const {
  96. assert(*this && "Attempt to dereference empty PooledStringPtr!");
  97. return S->getKeyData();
  98. }
  99. inline const char *end() const {
  100. assert(*this && "Attempt to dereference empty PooledStringPtr!");
  101. return S->getKeyData() + S->getKeyLength();
  102. }
  103. inline unsigned size() const {
  104. assert(*this && "Attempt to dereference empty PooledStringPtr!");
  105. return S->getKeyLength();
  106. }
  107. inline const char *operator*() const { return begin(); }
  108. inline explicit operator bool() const { return S != nullptr; }
  109. inline bool operator==(const PooledStringPtr &That) const { return S == That.S; }
  110. inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; }
  111. };
  112. } // End llvm namespace
  113. #endif