#pragma once
#include <wtf/text/UniquedStringImpl.h>
namespace WTF {
class RegisteredSymbolImpl;
class SymbolImpl : public UniquedStringImpl {
public:
using Flags = unsigned;
static constexpr Flags s_flagDefault = 0u;
static constexpr Flags s_flagIsNullSymbol = 0b001u;
static constexpr Flags s_flagIsRegistered = 0b010u;
static constexpr Flags s_flagIsPrivate = 0b100u;
unsigned hashForSymbol() const { return m_hashForSymbol; }
bool isNullSymbol() const { return m_flags & s_flagIsNullSymbol; }
bool isRegistered() const { return m_flags & s_flagIsRegistered; }
bool isPrivate() const { return m_flags & s_flagIsPrivate; }
SymbolRegistry* symbolRegistry() const;
RegisteredSymbolImpl* asRegisteredSymbolImpl();
WTF_EXPORT_PRIVATE static Ref<SymbolImpl> createNullSymbol();
WTF_EXPORT_PRIVATE static Ref<SymbolImpl> create(StringImpl& rep);
class StaticSymbolImpl : private StringImplShape {
WTF_MAKE_NONCOPYABLE(StaticSymbolImpl);
public:
template<unsigned characterCount>
constexpr StaticSymbolImpl(const char (&characters)[characterCount], Flags flags = s_flagDefault)
: StringImplShape(s_refCountFlagIsStaticString, characterCount - 1, characters,
s_hashFlag8BitBuffer | s_hashFlagDidReportCost | StringSymbol | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount), ConstructWithConstExpr)
, m_hashForSymbol(StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount)
, m_flags(flags)
{
}
template<unsigned characterCount>
constexpr StaticSymbolImpl(const char16_t (&characters)[characterCount], Flags flags = s_flagDefault)
: StringImplShape(s_refCountFlagIsStaticString, characterCount - 1, characters,
s_hashFlagDidReportCost | StringSymbol | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount), ConstructWithConstExpr)
, m_hashForSymbol(StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount)
, m_flags(flags)
{
}
operator SymbolImpl&()
{
return *reinterpret_cast<SymbolImpl*>(this);
}
StringImpl* m_owner { nullptr }; unsigned m_hashForSymbol;
Flags m_flags;
};
protected:
WTF_EXPORT_PRIVATE static unsigned nextHashForSymbol();
friend class StringImpl;
SymbolImpl(const LChar* characters, unsigned length, Ref<StringImpl>&& base, Flags flags = s_flagDefault)
: UniquedStringImpl(CreateSymbol, characters, length)
, m_owner(&base.leakRef())
, m_hashForSymbol(nextHashForSymbol())
, m_flags(flags)
{
ASSERT(StringImpl::tailOffset<StringImpl*>() == OBJECT_OFFSETOF(SymbolImpl, m_owner));
}
SymbolImpl(const UChar* characters, unsigned length, Ref<StringImpl>&& base, Flags flags = s_flagDefault)
: UniquedStringImpl(CreateSymbol, characters, length)
, m_owner(&base.leakRef())
, m_hashForSymbol(nextHashForSymbol())
, m_flags(flags)
{
ASSERT(StringImpl::tailOffset<StringImpl*>() == OBJECT_OFFSETOF(SymbolImpl, m_owner));
}
SymbolImpl(Flags flags = s_flagDefault)
: UniquedStringImpl(CreateSymbol)
, m_owner(StringImpl::empty())
, m_hashForSymbol(nextHashForSymbol())
, m_flags(flags | s_flagIsNullSymbol)
{
ASSERT(StringImpl::tailOffset<StringImpl*>() == OBJECT_OFFSETOF(SymbolImpl, m_owner));
}
StringImpl* m_owner;
unsigned m_hashForSymbol;
Flags m_flags { s_flagDefault };
};
static_assert(sizeof(SymbolImpl) == sizeof(SymbolImpl::StaticSymbolImpl), "");
class PrivateSymbolImpl : public SymbolImpl {
public:
WTF_EXPORT_PRIVATE static Ref<PrivateSymbolImpl> createNullSymbol();
WTF_EXPORT_PRIVATE static Ref<PrivateSymbolImpl> create(StringImpl& rep);
private:
PrivateSymbolImpl(const LChar* characters, unsigned length, Ref<StringImpl>&& base)
: SymbolImpl(characters, length, WTFMove(base), s_flagIsPrivate)
{
}
PrivateSymbolImpl(const UChar* characters, unsigned length, Ref<StringImpl>&& base)
: SymbolImpl(characters, length, WTFMove(base), s_flagIsPrivate)
{
}
PrivateSymbolImpl()
: SymbolImpl(s_flagIsPrivate)
{
}
};
class RegisteredSymbolImpl : public SymbolImpl {
private:
friend class StringImpl;
friend class SymbolImpl;
friend class SymbolRegistry;
SymbolRegistry* symbolRegistry() const { return m_symbolRegistry; }
void clearSymbolRegistry() { m_symbolRegistry = nullptr; }
static Ref<RegisteredSymbolImpl> create(StringImpl& rep, SymbolRegistry&);
RegisteredSymbolImpl(const LChar* characters, unsigned length, Ref<StringImpl>&& base, SymbolRegistry& registry)
: SymbolImpl(characters, length, WTFMove(base), s_flagIsRegistered)
, m_symbolRegistry(®istry)
{
}
RegisteredSymbolImpl(const UChar* characters, unsigned length, Ref<StringImpl>&& base, SymbolRegistry& registry)
: SymbolImpl(characters, length, WTFMove(base), s_flagIsRegistered)
, m_symbolRegistry(®istry)
{
}
SymbolRegistry* m_symbolRegistry;
};
inline unsigned StringImpl::symbolAwareHash() const
{
if (isSymbol())
return static_cast<const SymbolImpl*>(this)->hashForSymbol();
return hash();
}
inline unsigned StringImpl::existingSymbolAwareHash() const
{
if (isSymbol())
return static_cast<const SymbolImpl*>(this)->hashForSymbol();
return existingHash();
}
inline SymbolRegistry* SymbolImpl::symbolRegistry() const
{
if (isRegistered())
return static_cast<const RegisteredSymbolImpl*>(this)->symbolRegistry();
return nullptr;
}
inline RegisteredSymbolImpl* SymbolImpl::asRegisteredSymbolImpl()
{
ASSERT(isRegistered());
return static_cast<RegisteredSymbolImpl*>(this);
}
#if !ASSERT_DISABLED
template<> struct
ValueCheck<SymbolImpl*> {
static void checkConsistency(const SymbolImpl*) { }
};
template<> struct
ValueCheck<const SymbolImpl*> {
static void checkConsistency(const SymbolImpl*) { }
};
#endif
}
using WTF::SymbolImpl;
using WTF::PrivateSymbolImpl;
using WTF::RegisteredSymbolImpl;