From 54b71242fe5e416646e7db35524a45f7257918a9 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 28 Apr 2020 11:03:37 +0300 Subject: [PATCH] builder: add autofree compatibility; protect against b.str() twice in a row --- vlib/strings/builder.c.v | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/vlib/strings/builder.c.v b/vlib/strings/builder.c.v index e6d0563377..76a5f92d4f 100644 --- a/vlib/strings/builder.c.v +++ b/vlib/strings/builder.c.v @@ -6,6 +6,7 @@ module strings pub struct Builder { mut: buf []byte + str_calls int pub mut: len int initial_size int = 1 @@ -78,9 +79,20 @@ pub fn (b &Builder) after(n int) string { return string(copy) } +// NB: in order to avoid memleaks and additional memory copies, after a call to b.str(), +// the builder b will be empty. The returned string *owns* the accumulated data so far. pub fn (b mut Builder) str() string { + b.str_calls++ + if b.str_calls > 1 { + panic('builder.str() should be called just once.\n' + + 'If you want to reuse a builder, call b.free() first.') + } b.buf << `\0` - return string(b.buf,b.len) + s := string(b.buf,b.len) + bis := b.initial_size + b.buf = []byte{cap: bis} + b.len = 0 + return s } pub fn (b mut Builder) free() { @@ -91,5 +103,5 @@ pub fn (b mut Builder) free() { s := b.initial_size b.buf = []byte{cap: s} b.len = 0 + b.str_calls = 0 } -