github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/json/tokenizer/buffer.go (about) 1 // Copyright 2022 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package tokenizer 12 13 import "unicode/utf8" 14 15 // buffer, is very much like bytes.Buffer, but is simpler. In particular, 16 // because we don't need to support entirety of bytes.Buffer interface, the 17 // functions (s.a. AppendByte) are simpler, and as a result can be inlined. 18 type buffer struct { 19 buf []byte // We maintain an invariant that len(buf) == cap(buf). 20 l int // Current length. 21 } 22 23 // Reset resets the buffer for next use. 24 func (b *buffer) Reset() { 25 b.l = 0 26 } 27 28 // Bytes returns byte slice previously written. 29 // NB: We do not make a copy here. Returned buffer valid 30 // until next call to buffer. 31 func (b *buffer) Bytes() []byte { 32 return b.buf[:b.l] 33 } 34 35 // AppendByte appends byte to this buffer 36 func (b *buffer) AppendByte(c byte) { 37 if cap(b.buf)-b.l <= 1 { 38 b.buf = grow(b.buf, 1) 39 } 40 b.buf[b.l] = c 41 b.l++ 42 } 43 44 // Append appends buf to this buffer. 45 func (b *buffer) Append(buf []byte) { 46 if cap(b.buf)-b.l <= len(buf) { 47 b.buf = grow(b.buf, len(buf)) 48 } 49 copy(b.buf[b.l:], buf) 50 b.l += len(buf) 51 } 52 53 // AppendRune writes rune to this buffer. 54 func (b *buffer) AppendRune(r rune) { 55 // Compare as uint32 to correctly handle negative runes. 56 if uint32(r) < utf8.RuneSelf { 57 b.AppendByte(byte(r)) 58 return 59 } 60 61 if cap(b.buf)-b.l <= utf8.UTFMax { 62 b.buf = grow(b.buf, utf8.UTFMax) 63 } 64 65 n := utf8.EncodeRune(b.buf[b.l:b.l+utf8.UTFMax], r) 66 b.l += n 67 } 68 69 // smallBufferSize is an initial allocation minimal capacity. 70 const smallBufferSize = 64 71 72 // grow increases capacity of buf by at least n, and returns new buffer, 73 // containing a copy of buf. 74 func grow(buf []byte, n int) []byte { 75 if n < smallBufferSize { 76 n = smallBufferSize 77 } 78 79 if buf == nil { 80 return make([]byte, n) 81 } 82 83 // Cribbed from bytes.Buffer. 84 c := len(buf) + n // ensure enough space for n elements 85 if c < 2*cap(buf) { 86 c = 2 * cap(buf) 87 } 88 89 nb := append([]byte(nil), make([]byte, c)...) 90 copy(nb, buf) 91 // Make whole cap available since append may produce larger slice. 92 return nb[:cap(nb)] 93 }