diff --git a/vlib/strings/builder.v b/vlib/strings/builder.v index 7f06b616a0..ce4b6d3acc 100644 --- a/vlib/strings/builder.v +++ b/vlib/strings/builder.v @@ -118,24 +118,25 @@ pub fn (b &Builder) after(n int) string { return bytes2string(b.buf[n..]) } -// str returns all of the accumulated content of the buffer. -// 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. +// str returns a copy of all of the accumulated buffer content. +// NB: after a call to b.str(), the builder b should not be +// used again, you need to call b.free() first, or just leave +// it to be freed by -autofree when it goes out of scope. +// The returned string *owns* its own separate copy of the +// accumulated data that was in the string builder, before the +// .str() call. pub fn (mut b Builder) str() string { b.str_calls++ if b.str_calls > 1 { panic('builder.str() should be called just once.\nIf you want to reuse a builder, call b.free() first.') } b.buf << `\0` - s := tos(b.buf.data, b.len) - bis := b.initial_size - // free(b.buf.data) - b.buf = []byte{cap: bis} + s := unsafe { byteptr(memdup(b.buf.data, b.len)).vstring_with_len(b.len) } b.len = 0 return s } -// manually free the contents of the buffer +// free - manually free the contents of the buffer pub fn (mut b Builder) free() { unsafe { free(b.buf.data) } // b.buf = []byte{cap: b.initial_size} diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 4bcf35136a..65bbe19456 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -251,7 +251,6 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _SLIT("]"));') g.auto_str_funcs.writeln('\tstring res = strings__Builder_str(&sb);') g.auto_str_funcs.writeln('\tstrings__Builder_free(&sb);') - // g.auto_str_funcs.writeln('\treturn strings__Builder_str(&sb);') g.auto_str_funcs.writeln('\treturn res;') g.auto_str_funcs.writeln('}') } @@ -312,7 +311,9 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_f g.auto_str_funcs.writeln('\t\t}') g.auto_str_funcs.writeln('\t}') g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _SLIT("]"));') - g.auto_str_funcs.writeln('\treturn strings__Builder_str(&sb);') + g.auto_str_funcs.writeln('\tstring res = strings__Builder_str(&sb);') + g.auto_str_funcs.writeln('\tstrings__Builder_free(&sb);') + g.auto_str_funcs.writeln('\treturn res;') g.auto_str_funcs.writeln('}') } @@ -381,7 +382,9 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string) g.auto_str_funcs.writeln('\t\t}') g.auto_str_funcs.writeln('\t}') g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _SLIT("}"));') - g.auto_str_funcs.writeln('\treturn strings__Builder_str(&sb);') + g.auto_str_funcs.writeln('\tstring res = strings__Builder_str(&sb);') + g.auto_str_funcs.writeln('\tstrings__Builder_free(&sb);') + g.auto_str_funcs.writeln('\treturn res;') g.auto_str_funcs.writeln('}') } @@ -433,7 +436,9 @@ fn (mut g Gen) gen_str_for_multi_return(info table.MultiReturn, styp string, str } } g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, _SLIT(")"));') - g.auto_str_funcs.writeln('\treturn strings__Builder_str(&sb);') + g.auto_str_funcs.writeln('\tstring res = strings__Builder_str(&sb);') + g.auto_str_funcs.writeln('\tstrings__Builder_free(&sb);') + g.auto_str_funcs.writeln('\treturn res;') g.auto_str_funcs.writeln('}') }