replace fixed-size carry buffer with dynamic slice

Replace the fixed [256]byte carry buffer with a dynamic []byte slice to support arbitrarily long lines without heap allocation during accumulation. Update all carry buffer handling logic to use len(s.carry) and append instead of fixed-size copy operations.
This commit is contained in:
Eric Coissac
2026-03-11 17:05:34 +01:00
parent 09fbc217d3
commit 8c318c480e

View File

@@ -2,13 +2,12 @@ package obiformats
import "bytes"
// ropeScanner reads lines from a PieceOfChunk rope without heap allocation.
// The carry buffer (stack) handles lines that span two rope nodes.
// ropeScanner reads lines from a PieceOfChunk rope.
// The carry buffer handles lines that span two rope nodes; it grows as needed.
type ropeScanner struct {
current *PieceOfChunk
pos int
carry [256]byte // 256 gives ample margin for typical flat-file lines
carryN int
carry []byte
}
func newRopeScanner(rope *PieceOfChunk) *ropeScanner {
@@ -21,10 +20,10 @@ func newRopeScanner(rope *PieceOfChunk) *ropeScanner {
func (s *ropeScanner) ReadLine() []byte {
for {
if s.current == nil {
if s.carryN > 0 {
n := s.carryN
s.carryN = 0
return s.carry[:n]
if len(s.carry) > 0 {
line := s.carry
s.carry = s.carry[:0]
return line
}
return nil
}
@@ -34,13 +33,12 @@ func (s *ropeScanner) ReadLine() []byte {
if idx >= 0 {
var line []byte
if s.carryN == 0 {
if len(s.carry) == 0 {
line = data[:idx]
} else {
n := copy(s.carry[s.carryN:], data[:idx])
s.carryN += n
line = s.carry[:s.carryN]
s.carryN = 0
s.carry = append(s.carry, data[:idx]...)
line = s.carry
s.carry = s.carry[:0]
}
s.pos += idx + 1
if s.pos >= len(s.current.data) {
@@ -54,8 +52,7 @@ func (s *ropeScanner) ReadLine() []byte {
}
// No \n in this node: accumulate into carry and advance
n := copy(s.carry[s.carryN:], data)
s.carryN += n
s.carry = append(s.carry, data...)
s.current = s.current.Next()
s.pos = 0
}