Use loops instead of recursion in hot path
Small but measurable perf win
This commit is contained in:
parent
29a065049e
commit
31bd174a69
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue