Use loops instead of recursion in hot path

Small but measurable perf win
This commit is contained in:
Shadowfacts 2023-11-27 00:04:10 -05:00
parent 29a065049e
commit 31bd174a69
1 changed files with 120 additions and 112 deletions

View File

@ -636,6 +636,7 @@ private extension Tokenizer {
}
mutating func tokenizeTagName() -> Token? {
while true {
switch nextChar() {
case "\t", "\n", "\u{000C}", " ":
state = .beforeAttributeName
@ -660,16 +661,17 @@ private extension Tokenizer {
if case .startTag(var s, let selfClosing, let attributes) = currentToken {
s.append(c)
currentToken = .startTag(s, selfClosing: selfClosing, attributes: attributes)
return tokenizeTagName()
continue
} else if case .endTag(var s) = currentToken {
s.append(c)
currentToken = .endTag(s)
return tokenizeTagName()
continue
} else {
fatalError("bad current token")
}
}
}
}
mutating func tokenizeSelfClosingStartTag() -> Token? {
switch nextChar() {
@ -732,6 +734,7 @@ private extension Tokenizer {
}
mutating func tokenizeAttributeName() -> Token? {
while true {
let c = nextChar()
switch c {
case "\t", "\n", "\u{000C}", " ", "/", ">", nil:
@ -753,14 +756,15 @@ private extension Tokenizer {
if case .startTag(let s, let selfClosing, var attributes) = currentToken {
attributes[attributes.count - 1].name.append(c)
currentToken = .startTag(s, selfClosing: selfClosing, attributes: attributes)
return tokenizeAttributeName()
continue
} else if case .endTag(_) = currentToken {
return tokenizeAttributeName()
continue
} else {
fatalError("bad curren token")
}
}
}
}
mutating func tokenizeAfterAttributeName() -> Token? {
switch nextChar() {
@ -817,6 +821,7 @@ private extension Tokenizer {
}
mutating func tokenizeAttributeValue(quotes: AttributeValueQuotation) -> Token? {
while true {
if quotes == .unquoted {
switch nextChar() {
case "\t", "\n", "\u{000C}", " ":
@ -838,7 +843,9 @@ private extension Tokenizer {
if case .startTag(let s, let selfClosing, var attributes) = currentToken {
attributes[attributes.count - 1].value.append(c)
currentToken = .startTag(s, selfClosing: selfClosing, attributes: attributes)
return tokenizeAttributeValue(quotes: quotes)
continue
} else if case .endTag(_) = currentToken {
continue
} else {
fatalError("bad current token")
}
@ -868,15 +875,16 @@ private extension Tokenizer {
if case .startTag(let s, let selfClosing, var attributes) = currentToken {
attributes[attributes.count - 1].value.append(c)
currentToken = .startTag(s, selfClosing: selfClosing, attributes: attributes)
return tokenizeAttributeValue(quotes: quotes)
continue
} else if case .endTag(_) = currentToken {
return tokenizeAttributeValue(quotes: quotes)
continue
} else {
fatalError("bad current token")
}
}
}
}
}
mutating func tokenizeAfterAttributeValueQuoted() -> Token? {
switch nextChar() {