diff --git a/compiler/fn.v b/compiler/fn.v index 9bcf77c1e8..75104e9165 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -4,6 +4,8 @@ module main +import strings + const ( MaxLocalVars = 50 ) @@ -809,7 +811,7 @@ fn contains_capital(s string) bool { // "fn (int, string) int" fn (f Fn) typ_str() string { - mut sb := new_string_builder(50) + mut sb := strings.new_builder(50) sb.write('fn (') for i, arg in f.args { sb.write(arg.typ) diff --git a/compiler/main.v b/compiler/main.v index 14001137fe..5d6994d329 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -91,6 +91,7 @@ mut: show_c_cmd bool // `v -show_c_cmd` prints the C command to build program.v.c sanitize bool // use Clang's new "-fsanitize" option is_debug bool // keep compiled C files + no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers) } @@ -290,7 +291,7 @@ void init_consts();') } v.log('Done parsing.') // Write everything - mut d := new_string_builder(10000)// Just to avoid some unnecessary allocations + mut d := strings.new_builder(10000)// Just to avoid some unnecessary allocations d.writeln(cgen.includes.join_lines()) d.writeln(cgen.typedefs.join_lines()) d.writeln(cgen.types.join_lines()) @@ -872,7 +873,6 @@ fn new_v(args[]string) *V { 'utf8.v', 'map.v', 'option.v', - 'string_builder.v', ] // Location of all vlib files mut lang_dir := '' diff --git a/compiler/parser.v b/compiler/parser.v index 90a4700b30..90d835c78b 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -839,7 +839,7 @@ fn (p mut Parser) get_type() string { p.error('unknown type `$typ`') } if mul { - typ += repeat_char(`*`, nr_muls) + typ += strings.repeat(`*`, nr_muls) } // Register an []array type if is_arr2 { @@ -3175,7 +3175,7 @@ fn (p &Parser) building_v() bool { // fmt helpers fn (scanner mut Scanner) fgen(s string) { if scanner.fmt_line_empty { - s = repeat_char(`\t`, scanner.fmt_indent) + s + s = strings.repeat(`\t`, scanner.fmt_indent) + s } scanner.fmt_out.write(s) scanner.fmt_line_empty = false @@ -3183,7 +3183,7 @@ fn (scanner mut Scanner) fgen(s string) { fn (scanner mut Scanner) fgenln(s string) { if scanner.fmt_line_empty { - s = repeat_char(`\t`, scanner.fmt_indent) + s + s = strings.repeat(`\t`, scanner.fmt_indent) + s } scanner.fmt_out.writeln(s) scanner.fmt_line_empty = true diff --git a/compiler/scanner.v b/compiler/scanner.v index 527db200b9..0e2e183438 100644 --- a/compiler/scanner.v +++ b/compiler/scanner.v @@ -18,7 +18,7 @@ mut: started bool is_fmt bool // vfmt fields - fmt_out StringBuilder + fmt_out strings.Builder fmt_indent int fmt_line_empty bool } @@ -40,7 +40,7 @@ fn new_scanner(file_path string) *Scanner { scanner := &Scanner { file_path: file_path text: text - fmt_out: new_string_builder(1000) + fmt_out: strings.new_builder(1000) } // println('new scanner "$file_path" txt.len=$scanner.text.len') return scanner diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 4936480d3e..0848addcf4 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -25,6 +25,12 @@ fn new_array(mylen, cap, elm_size int) array { return arr } + +// TODO +pub fn _make(len, cap, elm_size int) array { + return new_array(len, cap, elm_size) +} + // Private function, used by V (`nums := [1, 2, 3]`) fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array { arr := array { diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 0086930933..eade49afe7 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -795,18 +795,6 @@ pub fn (c byte) is_white() bool { return i == 10 || i == 32 || i == 9 || i == 13 || c == `\r` } -// TODO move this to strings.repeat() -pub fn repeat_char(c byte, n int) string { - if n <= 0 { - return '' - } - mut arr := malloc(n + 1) - for i := 0; i < n; i++ { - arr[i] = c - } - arr[n] = `\0` - return tos(arr, n) -} pub fn (s string) hash() int { mut hash := int(0) diff --git a/vlib/builtin/string_builder.v b/vlib/strings/builder.v similarity index 50% rename from vlib/builtin/string_builder.v rename to vlib/strings/builder.v index 9660cb45aa..4cc0e8a7e7 100644 --- a/vlib/builtin/string_builder.v +++ b/vlib/strings/builder.v @@ -2,38 +2,39 @@ // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. -module builtin +module strings -struct StringBuilder { +struct Builder { +mut: buf []byte len int } -pub fn new_string_builder(initial_size int) StringBuilder { - return StringBuilder { - buf: new_array(0, initial_size, sizeof(byte)) +pub fn new_builder(initial_size int) Builder { + return Builder { + buf: _make(0, initial_size, sizeof(byte)) } } -pub fn (b mut StringBuilder) write(s string) { +pub fn (b mut Builder) write(s string) { b.buf._push_many(s.str, s.len) b.len += s.len } -pub fn (b mut StringBuilder) writeln(s string) { +pub fn (b mut Builder) writeln(s string) { b.buf._push_many(s.str, s.len) b.buf << `\n` b.len += s.len + 1 } -pub fn (b StringBuilder) str() string { +pub fn (b Builder) str() string { return tos(b.buf.data, b.len) } -pub fn (b StringBuilder) cut(n int) { +pub fn (b Builder) cut(n int) { b.len -= n } -pub fn (b mut StringBuilder) free() { +pub fn (b mut Builder) free() { C.free(b.buf.data) } diff --git a/vlib/strings/builder_test.v b/vlib/strings/builder_test.v new file mode 100644 index 0000000000..8831ce990c --- /dev/null +++ b/vlib/strings/builder_test.v @@ -0,0 +1,15 @@ +import strings + +fn test_sb() { + mut sb := strings.Builder{} + sb.write('hi') + sb.write('!') + sb.write('hello') + assert sb.str() == 'hi!hello' + sb = strings.new_builder(10) + sb.write('a') + sb.write('b') + println(sb.str()) + assert sb.str() == 'ab' +} + diff --git a/vlib/strings/strings.v b/vlib/strings/strings.v new file mode 100644 index 0000000000..ce32c38aa9 --- /dev/null +++ b/vlib/strings/strings.v @@ -0,0 +1,13 @@ +module strings + +pub fn repeat(c byte, n int) string { + if n <= 0 { + return '' + } + mut arr := malloc(n + 1) + for i := 0; i < n; i++ { + arr[i] = c + } + arr[n] = `\0` + return tos(arr, n) +} diff --git a/vlib/strings/strings_test.v b/vlib/strings/strings_test.v new file mode 100644 index 0000000000..2f87855181 --- /dev/null +++ b/vlib/strings/strings_test.v @@ -0,0 +1,6 @@ +import strings + +fn test_repeat() { + assert strings.repeat(`x`, 10) == 'xxxxxxxxxx' + assert strings.repeat(`a`, 1) == 'a' +}