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:
@ -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) }
|
||||
}
|
||||
|
@ -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')
|
||||
|
Reference in New Issue
Block a user