From b0d6c62255d6f92918be9d77ccfcae8ee2565290 Mon Sep 17 00:00:00 2001 From: Thomas Pelletier Date: Tue, 1 Jun 2021 09:51:59 -0400 Subject: [PATCH] Don't use bytes.Buffer when not necessary (#549) When parsing strings, they can be referenced directly from the document when they don't contain escaped characters. This avoids paying to cost of allocating (and sometimes growing) the bytes buffer unecessarily. --- parser.go | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/parser.go b/parser.go index b4caf73..aa97e2e 100644 --- a/parser.go +++ b/parser.go @@ -511,8 +511,6 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) { return nil, nil, err } - var builder bytes.Buffer - i := 3 // skip the immediate new line @@ -522,6 +520,21 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) { i += 2 } + // fast path + startIdx := i + endIdx := len(token) - len(`"""`) + for ; i < endIdx; i++ { + if token[i] == '\\' { + break + } + } + if i == endIdx { + return token[startIdx:endIdx], rest, nil + } + + var builder bytes.Buffer + builder.Write(token[startIdx:i]) + // The scanner ensures that the token starts and ends with quotes and that // escapes are balanced. for ; i < len(token)-3; i++ { @@ -673,11 +686,25 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, error) { return nil, nil, err } + // fast path + i := len(`"`) + startIdx := i + endIdx := len(token) - len(`"`) + for ; i < endIdx; i++ { + if token[i] == '\\' { + break + } + } + if i == endIdx { + return token[startIdx:endIdx], rest, nil + } + var builder bytes.Buffer + builder.Write(token[startIdx:i]) // The scanner ensures that the token starts and ends with quotes and that // escapes are balanced. - for i := 1; i < len(token)-1; i++ { + for ; i < len(token)-1; i++ { c := token[i] if c == '\\' { i++