diff --git a/vlib/strings/builder.c.v b/vlib/strings/builder.c.v index 5271d46c8c..2e7e7b1bb0 100644 --- a/vlib/strings/builder.c.v +++ b/vlib/strings/builder.c.v @@ -176,6 +176,28 @@ pub fn (mut b Builder) str() string { return s } +// ensure_cap ensures that the buffer has enough space for at least `n` bytes by growing the buffer if necessary +pub fn (mut b Builder) ensure_cap(n int) { + // code adapted from vlib/builtin/array.v + if n <= b.cap { + return + } + + new_data := vcalloc(n * b.element_size) + if b.data != voidptr(0) { + unsafe { vmemcpy(new_data, b.data, b.len * b.element_size) } + // TODO: the old data may be leaked when no GC is used (ref-counting?) + if b.flags.has(.noslices) { + unsafe { free(b.data) } + } + } + unsafe { + b.data = new_data + b.offset = 0 + b.cap = n + } +} + // free is for manually freeing the contents of the buffer [unsafe] pub fn (mut b Builder) free() { diff --git a/vlib/strings/builder_test.v b/vlib/strings/builder_test.v index 1bcc54a058..151e1b989a 100644 --- a/vlib/strings/builder_test.v +++ b/vlib/strings/builder_test.v @@ -112,3 +112,18 @@ fn test_write_runes() { x := sb.str() assert x == 'hello world' } + +fn test_ensure_cap() { + mut sb := strings.new_builder(0) + assert sb.cap == 0 + sb.ensure_cap(10) + assert sb.cap == 10 + sb.ensure_cap(10) + assert sb.cap == 10 + sb.ensure_cap(15) + assert sb.cap == 15 + sb.ensure_cap(10) + assert sb.cap == 15 + sb.ensure_cap(-1) + assert sb.cap == 15 +}