1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

strings: simplify Builder (#10263)

This commit is contained in:
Delyan Angelov
2021-05-31 14:21:06 +03:00
committed by GitHub
parent 8990114b4b
commit eac1e25c5d
14 changed files with 65 additions and 76 deletions

View File

@ -7,76 +7,59 @@ module strings
// dynamically growing buffer, then use the resulting large string. Using
// a string builder is much better for performance/memory usage than doing
// constantly string concatenation.
pub struct Builder {
pub mut:
buf []byte
len int
initial_size int = 1
}
pub type Builder = []byte
// new_builder returns a new string builder, with an initial capacity of `initial_size`
pub fn new_builder(initial_size int) Builder {
return Builder{
// buf: make(0, initial_size)
buf: []byte{cap: initial_size}
len: 0
initial_size: initial_size
}
}
// write_bytes appends `bytes` to the accumulated buffer
[deprecated: 'use Builder.write_ptr() instead']
[deprecated_after: '2021-04-18']
[unsafe]
pub fn (mut b Builder) write_bytes(bytes &byte, len int) {
unsafe { b.write_ptr(bytes, len) }
return Builder([]byte{cap: initial_size})
}
// write_ptr writes `len` bytes provided byteptr to the accumulated buffer
[unsafe]
pub fn (mut b Builder) write_ptr(ptr &byte, len int) {
unsafe { b.buf.push_many(ptr, len) }
b.len += len
unsafe { b.push_many(ptr, len) }
}
// write_b appends a single `data` byte to the accumulated buffer
pub fn (mut b Builder) write_b(data byte) {
b.buf << data
b.len++
b << data
}
// write implements the Writer interface
pub fn (mut b Builder) write(data []byte) ?int {
b.buf << data
b.len += data.len
b << data
return data.len
}
[inline]
pub fn (b &Builder) byte_at(n int) byte {
return unsafe { (&[]byte(b))[n] }
}
// write appends the string `s` to the buffer
[inline]
pub fn (mut b Builder) write_string(s string) {
if s == '' {
return
}
unsafe { b.buf.push_many(s.str, s.len) }
unsafe { b.push_many(s.str, s.len) }
// for c in s {
// b.buf << c
// }
// b.buf << []byte(s) // TODO
b.len += s.len
}
// go_back discards the last `n` bytes from the buffer
pub fn (mut b Builder) go_back(n int) {
b.buf.trim(b.buf.len - n)
b.len -= n
b.trim(b.len - n)
}
// cut_last cuts the last `n` bytes from the buffer and returns them
pub fn (mut b Builder) cut_last(n int) string {
res := b.buf[b.len - n..].bytestr()
b.buf.trim(b.buf.len - n)
b.len -= n
cut_pos := b.len - n
x := unsafe { (&[]byte(b))[cut_pos..] }
res := x.bytestr()
b.trim(cut_pos)
return res
}
@ -87,14 +70,13 @@ pub fn (mut b Builder) cut_to(pos int) string {
if pos > b.len {
return ''
}
return b.cut_last(b.buf.len - pos)
return b.cut_last(b.len - pos)
}
// go_back_to resets the buffer to the given position `pos`
// NB: pos should be < than the existing buffer length.
pub fn (mut b Builder) go_back_to(pos int) {
b.buf.trim(pos)
b.len = pos
b.trim(pos)
}
// writeln appends the string `s`, and then a newline character.
@ -103,10 +85,9 @@ pub fn (mut b Builder) writeln(s string) {
// for c in s {
// b.buf << c
// }
unsafe { b.buf.push_many(s.str, s.len) }
unsafe { b.push_many(s.str, s.len) }
// b.buf << []byte(s) // TODO
b.buf << byte(`\n`)
b.len += s.len + 1
b << byte(`\n`)
}
// buf == 'hello world'
@ -115,7 +96,8 @@ pub fn (b &Builder) last_n(n int) string {
if n > b.len {
return ''
}
return b.buf[b.len - n..].bytestr()
x := unsafe { (&[]byte(b))[b.len - n..] }
return x.bytestr()
}
// buf == 'hello world'
@ -124,7 +106,8 @@ pub fn (b &Builder) after(n int) string {
if n >= b.len {
return ''
}
return b.buf[n..].bytestr()
x := unsafe { (&[]byte(b))[n..] }
return x.bytestr()
}
// str returns a copy of all of the accumulated buffer content.
@ -135,17 +118,15 @@ pub fn (b &Builder) after(n int) string {
// accumulated data that was in the string builder, before the
// .str() call.
pub fn (mut b Builder) str() string {
b.buf << byte(0)
bcopy := unsafe { &byte(memdup(b.buf.data, b.buf.len)) }
s := unsafe { bcopy.vstring_with_len(b.len) }
b.len = 0
b.buf.trim(0)
b << byte(0)
bcopy := unsafe { &byte(memdup(b.data, b.len)) }
s := unsafe { bcopy.vstring_with_len(b.len - 1) }
b.trim(0)
return s
}
// free - manually free the contents of the buffer
[unsafe]
pub fn (mut b Builder) free() {
unsafe { free(b.buf.data) }
b.len = 0
unsafe { free(b.data) }
}

View File

@ -3,7 +3,7 @@ import strings
type MyInt = int
fn test_sb() {
mut sb := strings.Builder{}
mut sb := strings.new_builder(100)
sb.write_string('hi')
sb.write_string('!')
sb.write_string('hello')