#pragma once
#include "HTMLToken.h"
namespace WebCore {
class AtomicHTMLToken {
public:
explicit AtomicHTMLToken(HTMLToken&);
AtomicHTMLToken(HTMLToken::Type, const AtomicString& name, Vector<Attribute>&& = { });
AtomicHTMLToken(const AtomicHTMLToken&) = delete;
AtomicHTMLToken(AtomicHTMLToken&&) = default;
HTMLToken::Type type() const;
void setName(const AtomicString&);
const AtomicString& name() const;
bool forceQuirks() const;
String publicIdentifier() const;
String systemIdentifier() const;
Vector<Attribute>& attributes();
bool selfClosing() const;
const Vector<Attribute>& attributes() const;
const UChar* characters() const;
unsigned charactersLength() const;
bool charactersIsAll8BitData() const;
const String& comment() const;
private:
HTMLToken::Type m_type;
void initializeAttributes(const HTMLToken::AttributeList& attributes);
AtomicString m_name;
String m_data;
const UChar* m_externalCharacters; unsigned m_externalCharactersLength; bool m_externalCharactersIsAll8BitData;
std::unique_ptr<DoctypeData> m_doctypeData;
bool m_selfClosing; Vector<Attribute> m_attributes; };
const Attribute* findAttribute(const Vector<Attribute>&, const QualifiedName&);
bool hasAttribute(const Vector<Attribute>&, const AtomicString& localName);
inline HTMLToken::Type AtomicHTMLToken::type() const
{
return m_type;
}
inline const AtomicString& AtomicHTMLToken::name() const
{
ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag || m_type == HTMLToken::DOCTYPE);
return m_name;
}
inline void AtomicHTMLToken::setName(const AtomicString& name)
{
ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag || m_type == HTMLToken::DOCTYPE);
m_name = name;
}
inline bool AtomicHTMLToken::selfClosing() const
{
ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag);
return m_selfClosing;
}
inline Vector<Attribute>& AtomicHTMLToken::attributes()
{
ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag);
return m_attributes;
}
inline const Vector<Attribute>& AtomicHTMLToken::attributes() const
{
ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag);
return m_attributes;
}
inline const UChar* AtomicHTMLToken::characters() const
{
ASSERT(m_type == HTMLToken::Character);
return m_externalCharacters;
}
inline unsigned AtomicHTMLToken::charactersLength() const
{
ASSERT(m_type == HTMLToken::Character);
return m_externalCharactersLength;
}
inline bool AtomicHTMLToken::charactersIsAll8BitData() const
{
return m_externalCharactersIsAll8BitData;
}
inline const String& AtomicHTMLToken::comment() const
{
ASSERT(m_type == HTMLToken::Comment);
return m_data;
}
inline bool AtomicHTMLToken::forceQuirks() const
{
ASSERT(m_type == HTMLToken::DOCTYPE);
return m_doctypeData->forceQuirks;
}
inline String AtomicHTMLToken::publicIdentifier() const
{
ASSERT(m_type == HTMLToken::DOCTYPE);
if (!m_doctypeData->hasPublicIdentifier)
return String();
return StringImpl::create8BitIfPossible(m_doctypeData->publicIdentifier);
}
inline String AtomicHTMLToken::systemIdentifier() const
{
if (!m_doctypeData->hasSystemIdentifier)
return String();
return StringImpl::create8BitIfPossible(m_doctypeData->systemIdentifier);
}
inline const Attribute* findAttribute(const Vector<Attribute>& attributes, const QualifiedName& name)
{
for (auto& attribute : attributes) {
if (attribute.name().matches(name))
return &attribute;
}
return nullptr;
}
inline bool hasAttribute(const Vector<Attribute>& attributes, const AtomicString& localName)
{
for (auto& attribute : attributes) {
if (attribute.localName() == localName)
return true;
}
return false;
}
inline void AtomicHTMLToken::initializeAttributes(const HTMLToken::AttributeList& attributes)
{
unsigned size = attributes.size();
if (!size)
return;
m_attributes.reserveInitialCapacity(size);
for (auto& attribute : attributes) {
if (attribute.name.isEmpty())
continue;
AtomicString localName(attribute.name);
if (!hasAttribute(m_attributes, localName))
m_attributes.uncheckedAppend(Attribute(QualifiedName(nullAtom(), localName, nullAtom()), AtomicString(attribute.value)));
}
}
inline AtomicHTMLToken::AtomicHTMLToken(HTMLToken& token)
: m_type(token.type())
{
switch (m_type) {
case HTMLToken::Uninitialized:
ASSERT_NOT_REACHED();
return;
case HTMLToken::DOCTYPE:
m_name = AtomicString(token.name());
m_doctypeData = token.releaseDoctypeData();
return;
case HTMLToken::EndOfFile:
return;
case HTMLToken::StartTag:
case HTMLToken::EndTag:
m_selfClosing = token.selfClosing();
m_name = AtomicString(token.name());
initializeAttributes(token.attributes());
return;
case HTMLToken::Comment:
if (token.commentIsAll8BitData())
m_data = String::make8BitFrom16BitSource(token.comment());
else
m_data = String(token.comment());
return;
case HTMLToken::Character:
m_externalCharacters = token.characters().data();
m_externalCharactersLength = token.characters().size();
m_externalCharactersIsAll8BitData = token.charactersIsAll8BitData();
return;
}
ASSERT_NOT_REACHED();
}
inline AtomicHTMLToken::AtomicHTMLToken(HTMLToken::Type type, const AtomicString& name, Vector<Attribute>&& attributes)
: m_type(type)
, m_name(name)
, m_selfClosing(false)
, m_attributes(WTFMove(attributes))
{
ASSERT(type == HTMLToken::StartTag || type == HTMLToken::EndTag);
}
}