#ifndef LLVM_SUPPORT_STRINGPOOL_H
#define LLVM_SUPPORT_STRINGPOOL_H
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <new>
namespace llvm {
class PooledStringPtr;
class StringPool {
struct PooledString {
StringPool *Pool; unsigned Refcount;
public:
PooledString() : Pool(nullptr), Refcount(0) { }
};
friend class PooledStringPtr;
typedef StringMap<PooledString> table_t;
typedef StringMapEntry<PooledString> entry_t;
table_t InternTable;
public:
StringPool();
~StringPool();
PooledStringPtr intern(StringRef Str);
inline bool empty() const { return InternTable.empty(); }
};
class PooledStringPtr {
typedef StringPool::entry_t entry_t;
entry_t *S;
public:
PooledStringPtr() : S(nullptr) {}
explicit PooledStringPtr(entry_t *E) : S(E) {
if (S) ++S->getValue().Refcount;
}
PooledStringPtr(const PooledStringPtr &That) : S(That.S) {
if (S) ++S->getValue().Refcount;
}
PooledStringPtr &operator=(const PooledStringPtr &That) {
if (S != That.S) {
clear();
S = That.S;
if (S) ++S->getValue().Refcount;
}
return *this;
}
void clear() {
if (!S)
return;
if (--S->getValue().Refcount == 0) {
S->getValue().Pool->InternTable.remove(S);
S->Destroy();
}
S = nullptr;
}
~PooledStringPtr() { clear(); }
inline const char *begin() const {
assert(*this && "Attempt to dereference empty PooledStringPtr!");
return S->getKeyData();
}
inline const char *end() const {
assert(*this && "Attempt to dereference empty PooledStringPtr!");
return S->getKeyData() + S->getKeyLength();
}
inline unsigned size() const {
assert(*this && "Attempt to dereference empty PooledStringPtr!");
return S->getKeyLength();
}
inline const char *operator*() const { return begin(); }
inline LLVM_EXPLICIT operator bool() const { return S != nullptr; }
inline bool operator==(const PooledStringPtr &That) const { return S == That.S; }
inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; }
};
}
#endif