StructHtmlToken
Struct representation of an HTML token.
using AngleSharp.Common;
using AngleSharp.Dom;
using AngleSharp.Text;
using System;
using System.Runtime.CompilerServices;
namespace AngleSharp.Html.Parser.Tokens.Struct
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public struct StructHtmlToken
{
[System.Runtime.CompilerServices.NullableContext(0)]
private sealed class StructTokenDoctypeData
{
public bool Quirks { get; set; }
public StringOrMemory? PublicIdentifier { get; set; }
public StringOrMemory? SystemIdentifier { get; set; }
}
private readonly HtmlTokenType _type;
private readonly TextPosition _position;
private StringOrMemory _name;
private StructAttributes _attributes;
private bool _selfClosing;
[System.Runtime.CompilerServices.Nullable(2)]
private StructTokenDoctypeData _structTokenDoctypeData;
private static readonly char[] Spaces = new char[5] {
' ',
'\t',
'\n',
'\r',
''
};
public bool IsDoctype => _type == HtmlTokenType.Doctype;
public bool IsTag {
get {
HtmlTokenType type = _type;
if (type - 1 > HtmlTokenType.StartTag)
return false;
return true;
}
}
public bool HasContent {
get {
for (int i = 0; i < _name.Length; i++) {
if (!_name[i].IsSpaceCharacter())
return true;
}
return false;
}
}
public StringOrMemory Name {
get {
return _name;
}
set {
_name = value;
}
}
public bool IsEmpty => _name.Length == 0;
public StringOrMemory Data => Name;
public TextPosition Position => _position;
public bool IsHtmlCompatible {
get {
if (_type != HtmlTokenType.StartTag)
return _type == HtmlTokenType.Character;
return true;
}
}
public bool IsSvg => IsStartTag(TagNames.Svg);
public bool IsMathCompatible {
get {
if (IsStartTag("mglyph") || IsStartTag("malignmark"))
return _type == HtmlTokenType.Character;
return true;
}
}
public HtmlTokenType Type => _type;
public bool IsProcessingInstruction {
[System.Runtime.CompilerServices.IsReadOnly]
get;
internal set;
}
public bool IsSelfClosing {
get {
return _selfClosing;
}
set {
_selfClosing = value;
}
}
public StructAttributes Attributes => _attributes;
public bool IsQuirksForced {
get {
return _structTokenDoctypeData?.Quirks ?? false;
}
set {
if (_structTokenDoctypeData == null)
_structTokenDoctypeData = new StructTokenDoctypeData();
_structTokenDoctypeData.Quirks = value;
}
}
public bool IsPublicIdentifierMissing {
get {
StructTokenDoctypeData structTokenDoctypeData = _structTokenDoctypeData;
if (structTokenDoctypeData == null)
return true;
return !structTokenDoctypeData.PublicIdentifier.HasValue;
}
}
public bool IsSystemIdentifierMissing {
get {
StructTokenDoctypeData structTokenDoctypeData = _structTokenDoctypeData;
if (structTokenDoctypeData == null)
return true;
return !structTokenDoctypeData.SystemIdentifier.HasValue;
}
}
public StringOrMemory PublicIdentifier {
get {
return (_structTokenDoctypeData?.PublicIdentifier).GetValueOrDefault();
}
set {
if (_structTokenDoctypeData == null)
_structTokenDoctypeData = new StructTokenDoctypeData();
_structTokenDoctypeData.PublicIdentifier = value;
}
}
public StringOrMemory SystemIdentifier {
get {
return (_structTokenDoctypeData?.SystemIdentifier).GetValueOrDefault();
}
set {
if (_structTokenDoctypeData == null)
_structTokenDoctypeData = new StructTokenDoctypeData();
_structTokenDoctypeData.SystemIdentifier = value;
}
}
public bool IsLimitedQuirks {
get {
StringOrMemory publicIdentifier = PublicIdentifier;
StringOrMemory systemIdentifier = SystemIdentifier;
if (!publicIdentifier.StartsWith("-//W3C//DTD XHTML 1.0 Frameset//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD XHTML 1.0 Transitional//", StringComparison.OrdinalIgnoreCase) && !systemIdentifier.StartsWith("-//W3C//DTD HTML 4.01 Frameset//", StringComparison.OrdinalIgnoreCase))
return systemIdentifier.StartsWith("-//W3C//DTD HTML 4.01 Transitional//", StringComparison.OrdinalIgnoreCase);
return true;
}
}
public bool IsFullQuirks {
get {
StringOrMemory publicIdentifier = PublicIdentifier;
if (!IsQuirksForced && !(Name != "html") && !publicIdentifier.StartsWith("+//Silmaril//dtd html Pro v0r11 19970101//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//AS//DTD HTML 3.0 asWedit + extensions//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.0 Level 1//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.0 Level 2//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.0 Strict Level 1//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.0 Strict Level 2//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.0 Strict//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 2.1E//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 3.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 3.2 Final//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 3.2//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML 3//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Level 0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Level 1//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Level 2//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Level 3//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Strict Level 0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Strict Level 1//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Strict Level 2//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Strict Level 3//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML Strict//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//IETF//DTD HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Metrius//DTD Metrius Presentational//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Microsoft//DTD Internet Explorer 2.0 Tables//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Microsoft//DTD Internet Explorer 3.0 Tables//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Netscape Comm. Corp.//DTD HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Netscape Comm. Corp.//DTD Strict HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//O'Reilly and Associates//DTD HTML 2.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//O'Reilly and Associates//DTD HTML Extended 1.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Spyglass//DTD HTML 2.0 Extended//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//SQ//DTD HTML 2.0 HoTMetaL + extensions//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Sun Microsystems Corp.//DTD HotJava HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//Sun Microsystems Corp.//DTD HotJava Strict HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 3 1995-03-24//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 3.2 Draft//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 3.2 Final//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 3.2//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 3.2S Draft//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 4.0 Frameset//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML 4.0 Transitional//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML Experimental 19960712//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD HTML Experimental 970421//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3C//DTD W3 HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//W3O//DTD W3 HTML 3.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.Isi("-//W3O//DTD W3 HTML Strict 3.0//EN//") && !publicIdentifier.StartsWith("-//WebTechs//DTD Mozilla HTML 2.0//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.StartsWith("-//WebTechs//DTD Mozilla HTML//", StringComparison.OrdinalIgnoreCase) && !publicIdentifier.Isi("-/W3C/DTD HTML 4.0 Transitional/EN") && !publicIdentifier.Isi("HTML") && !StringOrMemoryExtensions.Equals(SystemIdentifier, "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd", StringComparison.OrdinalIgnoreCase) && (!IsSystemIdentifierMissing || !publicIdentifier.StartsWith("-//W3C//DTD HTML 4.01 Frameset//", StringComparison.OrdinalIgnoreCase))) {
if (IsSystemIdentifierMissing)
return publicIdentifier.StartsWith("-//W3C//DTD HTML 4.01 Transitional//", StringComparison.OrdinalIgnoreCase);
return false;
}
return true;
}
}
public bool IsValid {
get {
if (Name == "html") {
if (!IsPublicIdentifierMissing) {
StringOrMemory publicIdentifier = PublicIdentifier;
if (publicIdentifier == "-//W3C//DTD HTML 4.0//EN") {
if (!IsSystemIdentifierMissing)
return SystemIdentifier == "http://www.w3.org/TR/REC-html40/strict.dtd";
return true;
}
if (publicIdentifier == "-//W3C//DTD HTML 4.01//EN") {
if (!IsSystemIdentifierMissing)
return SystemIdentifier == "http://www.w3.org/TR/html4/strict.dtd";
return true;
}
if (publicIdentifier == "-//W3C//DTD XHTML 1.0 Strict//EN")
return SystemIdentifier == "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
if (publicIdentifier == "-//W3C//DTD XHTML 1.1//EN")
return SystemIdentifier == "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd";
}
if (!IsSystemIdentifierMissing)
return SystemIdentifier == "about:legacy-compat";
return true;
}
return false;
}
}
private StructHtmlToken(HtmlTokenType type, TextPosition position, StringOrMemory name = default(StringOrMemory))
{
_attributes = default(StructAttributes);
_selfClosing = false;
_structTokenDoctypeData = null;
IsProcessingInstruction = false;
_type = type;
_position = position;
_name = name;
}
internal static StructHtmlToken Skipped(HtmlTokenType htmlTokenType, TextPosition position)
{
return new StructHtmlToken(htmlTokenType, position, default(StringOrMemory));
}
internal static StructHtmlToken Doctype(bool quirksForced, TextPosition position)
{
StructHtmlToken result = new StructHtmlToken(HtmlTokenType.Doctype, position, default(StringOrMemory));
result._structTokenDoctypeData = new StructTokenDoctypeData {
Quirks = quirksForced
};
return result;
}
internal static StructHtmlToken TagOpen(TextPosition position)
{
return new StructHtmlToken(HtmlTokenType.StartTag, position, default(StringOrMemory));
}
internal static StructHtmlToken Open(StringOrMemory name)
{
return new StructHtmlToken(HtmlTokenType.StartTag, TextPosition.Empty, name);
}
internal static StructHtmlToken TagClose(TextPosition position)
{
return new StructHtmlToken(HtmlTokenType.EndTag, position, default(StringOrMemory));
}
internal static StructHtmlToken Close(StringOrMemory s)
{
return new StructHtmlToken(HtmlTokenType.EndTag, TextPosition.Empty, s);
}
internal static StructHtmlToken Character(StringOrMemory name, TextPosition position)
{
return new StructHtmlToken(HtmlTokenType.Character, position, name);
}
internal static StructHtmlToken Comment(StringOrMemory name, TextPosition position)
{
return new StructHtmlToken(HtmlTokenType.Comment, position, name);
}
internal static StructHtmlToken ProcessingInstruction(StringOrMemory name, TextPosition position)
{
StructHtmlToken result = new StructHtmlToken(HtmlTokenType.Comment, position, name);
result.IsProcessingInstruction = true;
return result;
}
internal static StructHtmlToken EndOfFile(TextPosition position)
{
return new StructHtmlToken(HtmlTokenType.EndOfFile, position, default(StringOrMemory));
}
public StringOrMemory TrimStart()
{
int i;
ReadOnlyMemory<char> memory;
for (i = 0; i < _name.Length; i++) {
memory = _name.Memory;
if (!memory.Span[i].IsSpaceCharacter())
break;
}
memory = _name.Memory;
ReadOnlyMemory<char> memory2 = memory.Slice(0, i);
memory = _name.Memory;
_name = new StringOrMemory(memory.Slice(i));
return new StringOrMemory(memory2);
}
public void CleanStart()
{
int i;
ReadOnlyMemory<char> memory;
for (i = 0; i < _name.Length; i++) {
memory = _name.Memory;
if (!memory.Span[i].IsSpaceCharacter())
break;
}
if (i > 0) {
memory = _name.Memory;
_name = new StringOrMemory(memory.Slice(i));
}
}
public void RemoveNewLine()
{
if (_name.Length > 0 && _name[0] == '\n')
_name = new StringOrMemory(_name.Memory.Slice(1));
}
public bool IsStartTag(string name)
{
if (_type == HtmlTokenType.StartTag)
return _name.Is(name);
return false;
}
public void AddAttribute(StringOrMemory name, TextPosition position)
{
_attributes.Add(new MemoryHtmlAttributeToken(position, name, StringOrMemory.Empty));
}
public void AddAttribute(StringOrMemory name, StringOrMemory value)
{
_attributes.Add(new MemoryHtmlAttributeToken(TextPosition.Empty, name, value));
}
public void SetAttributeValue(StringOrMemory value)
{
int id = _attributes.Count - 1;
MemoryHtmlAttributeToken memoryHtmlAttributeToken = _attributes[id];
_attributes[id] = new MemoryHtmlAttributeToken(memoryHtmlAttributeToken.Position, memoryHtmlAttributeToken.Name, value);
}
public StringOrMemory GetAttribute(StringOrMemory name)
{
if (_attributes.Count == 0)
return StringOrMemory.Empty;
for (int i = 0; i != _attributes.Count; i++) {
MemoryHtmlAttributeToken memoryHtmlAttributeToken = _attributes[i];
if (memoryHtmlAttributeToken.Name.Is(name))
return memoryHtmlAttributeToken.Value;
}
return StringOrMemory.Empty;
}
public void RemoveAttributeAt(int i)
{
if (i < _attributes.Count)
_attributes.RemoveAt(i);
}
public HtmlToken ToHtmlToken()
{
HtmlTokenType type = Type;
StringOrMemory stringOrMemory;
if (type == HtmlTokenType.Doctype) {
if (_structTokenDoctypeData == null)
return new HtmlDoctypeToken(false, _position) {
IsProcessingInstruction = IsProcessingInstruction,
Name = _name.ToString()
};
HtmlDoctypeToken htmlDoctypeToken = new HtmlDoctypeToken(_structTokenDoctypeData.Quirks, _position) {
IsProcessingInstruction = IsProcessingInstruction,
Name = _name.ToString()
};
if (_structTokenDoctypeData.PublicIdentifier.HasValue) {
HtmlDoctypeToken htmlDoctypeToken2 = htmlDoctypeToken;
stringOrMemory = _structTokenDoctypeData.PublicIdentifier.Value;
htmlDoctypeToken2.PublicIdentifier = stringOrMemory.ToString();
}
if (_structTokenDoctypeData.SystemIdentifier.HasValue) {
HtmlDoctypeToken htmlDoctypeToken3 = htmlDoctypeToken;
stringOrMemory = _structTokenDoctypeData.SystemIdentifier.Value;
htmlDoctypeToken3.SystemIdentifier = stringOrMemory.ToString();
}
return htmlDoctypeToken;
}
if (type - 1 <= HtmlTokenType.StartTag) {
HtmlTagToken htmlTagToken = new HtmlTagToken(Type, _position, _name.ToString()) {
IsSelfClosing = IsSelfClosing,
IsProcessingInstruction = IsProcessingInstruction
};
for (int i = 0; i < _attributes.Count; i++) {
MemoryHtmlAttributeToken memoryHtmlAttributeToken = _attributes[i];
HtmlTagToken htmlTagToken2 = htmlTagToken;
stringOrMemory = memoryHtmlAttributeToken.Name;
htmlTagToken2.AddAttribute(stringOrMemory.ToString(), memoryHtmlAttributeToken.Position);
HtmlTagToken htmlTagToken3 = htmlTagToken;
stringOrMemory = memoryHtmlAttributeToken.Value;
htmlTagToken3.SetAttributeValue(stringOrMemory.ToString());
}
return htmlTagToken;
}
return new HtmlToken(Type, _position, _name.ToString()) {
IsProcessingInstruction = IsProcessingInstruction
};
}
}
}