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