mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
strings: run v fmt (#7438)
This commit is contained in:
parent
fade162471
commit
6c341a77f5
@ -58,6 +58,8 @@ const (
|
|||||||
'vlib/v/vmod/',
|
'vlib/v/vmod/',
|
||||||
'vlib/gg/gg.v',
|
'vlib/gg/gg.v',
|
||||||
'vlib/os/',
|
'vlib/os/',
|
||||||
|
'vlib/semver/',
|
||||||
|
'vlib/strings/',
|
||||||
'vlib/time/',
|
'vlib/time/',
|
||||||
'vlib/builtin/array_test.v',
|
'vlib/builtin/array_test.v',
|
||||||
]
|
]
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
module strings
|
module strings
|
||||||
|
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
mut:
|
mut:
|
||||||
buf []byte
|
buf []byte
|
||||||
pub mut:
|
pub mut:
|
||||||
len int
|
len int
|
||||||
initial_size int = 1
|
initial_size int = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_builder(initial_size int) Builder {
|
pub fn new_builder(initial_size int) Builder {
|
||||||
return Builder {
|
return Builder{
|
||||||
buf: make(0, initial_size, sizeof(byte))
|
buf: make(0, initial_size, sizeof(byte))
|
||||||
initial_size: initial_size
|
initial_size: initial_size
|
||||||
}
|
}
|
||||||
@ -26,19 +25,19 @@ pub fn (mut b Builder) write_b(data byte) {
|
|||||||
|
|
||||||
pub fn (mut b Builder) write(s string) {
|
pub fn (mut b Builder) write(s string) {
|
||||||
b.buf.push_many(s.str, s.len)
|
b.buf.push_many(s.str, s.len)
|
||||||
//b.buf << []byte(s) // TODO
|
// b.buf << []byte(s) // TODO
|
||||||
b.len += s.len
|
b.len += s.len
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut b Builder) writeln(s string) {
|
pub fn (mut b Builder) writeln(s string) {
|
||||||
b.buf.push_many(s.str, s.len)
|
b.buf.push_many(s.str, s.len)
|
||||||
//b.buf << []byte(s) // TODO
|
// b.buf << []byte(s) // TODO
|
||||||
b.buf << `\n`
|
b.buf << `\n`
|
||||||
b.len += s.len + 1
|
b.len += s.len + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b Builder) str() string {
|
pub fn (b Builder) str() string {
|
||||||
return unsafe { byteptr(b.buf.data).vstring_with_len(b.len) }
|
return unsafe {byteptr(b.buf.data).vstring_with_len(b.len)}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut b Builder) cut(n int) {
|
pub fn (mut b Builder) cut(n int) {
|
||||||
|
@ -3,8 +3,11 @@
|
|||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module strings
|
module strings
|
||||||
|
|
||||||
|
// strings.Builder is used to efficiently append many strings to a large
|
||||||
|
// 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 struct Builder {
|
||||||
// TODO
|
|
||||||
pub mut:
|
pub mut:
|
||||||
buf []byte
|
buf []byte
|
||||||
str_calls int
|
str_calls int
|
||||||
@ -12,9 +15,10 @@ pub mut:
|
|||||||
initial_size int = 1
|
initial_size int = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// new_builder returns a new string builder, with an initial capacity of `initial_size`
|
||||||
pub fn new_builder(initial_size int) Builder {
|
pub fn new_builder(initial_size int) Builder {
|
||||||
return Builder{
|
return Builder{
|
||||||
//buf: make(0, initial_size)
|
// buf: make(0, initial_size)
|
||||||
buf: []byte{cap: initial_size}
|
buf: []byte{cap: initial_size}
|
||||||
str_calls: 0
|
str_calls: 0
|
||||||
len: 0
|
len: 0
|
||||||
@ -22,16 +26,19 @@ pub fn new_builder(initial_size int) Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write_bytes appends `bytes` to the accumulated buffer
|
||||||
pub fn (mut b Builder) write_bytes(bytes byteptr, howmany int) {
|
pub fn (mut b Builder) write_bytes(bytes byteptr, howmany int) {
|
||||||
b.buf.push_many(bytes, howmany)
|
b.buf.push_many(bytes, howmany)
|
||||||
b.len += howmany
|
b.len += howmany
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write_b appends a single `data` byte to the accumulated buffer
|
||||||
pub fn (mut b Builder) write_b(data byte) {
|
pub fn (mut b Builder) write_b(data byte) {
|
||||||
b.buf << data
|
b.buf << data
|
||||||
b.len++
|
b.len++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write appends the string `s` to the buffer
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut b Builder) write(s string) {
|
pub fn (mut b Builder) write(s string) {
|
||||||
if s == '' {
|
if s == '' {
|
||||||
@ -45,21 +52,23 @@ pub fn (mut b Builder) write(s string) {
|
|||||||
b.len += s.len
|
b.len += s.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// go_back discards the last `n` bytes from the buffer
|
||||||
pub fn (mut b Builder) go_back(n int) {
|
pub fn (mut b Builder) go_back(n int) {
|
||||||
b.buf.trim(b.buf.len-n)
|
b.buf.trim(b.buf.len - n)
|
||||||
b.len -= n
|
b.len -= n
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytes2string(b []byte) string {
|
fn bytes2string(b []byte) string {
|
||||||
mut copy := b.clone()
|
mut copy := b.clone()
|
||||||
copy << byte(`\0`)
|
copy << byte(`\0`)
|
||||||
res := tos(copy.data, copy.len-1)
|
res := tos(copy.data, copy.len - 1)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cut_last cuts the last `n` bytes from the buffer and returns them
|
||||||
pub fn (mut b Builder) cut_last(n int) string {
|
pub fn (mut b Builder) cut_last(n int) string {
|
||||||
res := bytes2string( b.buf[b.len-n..] )
|
res := bytes2string(b.buf[b.len - n..])
|
||||||
b.buf.trim(b.buf.len-n)
|
b.buf.trim(b.buf.len - n)
|
||||||
b.len -= n
|
b.len -= n
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -72,12 +81,14 @@ pub fn (mut b Builder) cut_to(pos int) string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
// 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) {
|
pub fn (mut b Builder) go_back_to(pos int) {
|
||||||
b.buf.trim(pos)
|
b.buf.trim(pos)
|
||||||
b.len = pos
|
b.len = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeln appends the string `s`, and then a newline character.
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut b Builder) writeln(s string) {
|
pub fn (mut b Builder) writeln(s string) {
|
||||||
// for c in s {
|
// for c in s {
|
||||||
@ -95,7 +106,7 @@ pub fn (b &Builder) last_n(n int) string {
|
|||||||
if n > b.len {
|
if n > b.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return bytes2string( b.buf[b.len-n..] )
|
return bytes2string(b.buf[b.len - n..])
|
||||||
}
|
}
|
||||||
|
|
||||||
// buf == 'hello world'
|
// buf == 'hello world'
|
||||||
@ -104,31 +115,30 @@ pub fn (b &Builder) after(n int) string {
|
|||||||
if n >= b.len {
|
if n >= b.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return bytes2string( b.buf[n..] )
|
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(),
|
// 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.
|
// the builder b will be empty. The returned string *owns* the accumulated data so far.
|
||||||
pub fn (mut b Builder) str() string {
|
pub fn (mut b Builder) str() string {
|
||||||
b.str_calls++
|
b.str_calls++
|
||||||
if b.str_calls > 1 {
|
if b.str_calls > 1 {
|
||||||
panic('builder.str() should be called just once.\n' +
|
panic('builder.str() should be called just once.\nIf you want to reuse a builder, call b.free() first.')
|
||||||
'If you want to reuse a builder, call b.free() first.')
|
|
||||||
}
|
}
|
||||||
b.buf << `\0`
|
b.buf << `\0`
|
||||||
s := tos(b.buf.data, b.len)
|
s := tos(b.buf.data, b.len)
|
||||||
bis := b.initial_size
|
bis := b.initial_size
|
||||||
//free(b.buf.data)
|
// free(b.buf.data)
|
||||||
b.buf = []byte{cap: bis}
|
b.buf = []byte{cap: bis}
|
||||||
b.len = 0
|
b.len = 0
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// manually free the contents of the buffer
|
||||||
pub fn (mut b Builder) free() {
|
pub fn (mut b Builder) free() {
|
||||||
unsafe{
|
unsafe {free(b.buf.data)}
|
||||||
free(b.buf.data)
|
// b.buf = []byte{cap: b.initial_size}
|
||||||
}
|
|
||||||
//b.buf = []byte{cap: b.initial_size}
|
|
||||||
b.len = 0
|
b.len = 0
|
||||||
b.str_calls = 0
|
b.str_calls = 0
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,13 @@ fn test_sb() {
|
|||||||
y := MyInt(20)
|
y := MyInt(20)
|
||||||
sb.writeln('x = $x y = $y')
|
sb.writeln('x = $x y = $y')
|
||||||
res := sb.str()
|
res := sb.str()
|
||||||
assert res[res.len-1] == `\n`
|
assert res[res.len - 1] == `\n`
|
||||||
println('"$res"')
|
println('"$res"')
|
||||||
assert res.trim_space() == 'x = 10 y = 20'
|
assert res.trim_space() == 'x = 10 y = 20'
|
||||||
//
|
//
|
||||||
sb = strings.new_builder(10)
|
sb = strings.new_builder(10)
|
||||||
sb.write('x = $x y = $y')
|
sb.write('x = $x y = $y')
|
||||||
assert sb.str() == 'x = 10 y = 20'
|
assert sb.str() == 'x = 10 y = 20'
|
||||||
|
|
||||||
$if !windows {
|
$if !windows {
|
||||||
// TODO msvc bug
|
// TODO msvc bug
|
||||||
sb = strings.new_builder(10)
|
sb = strings.new_builder(10)
|
||||||
@ -49,7 +48,7 @@ const (
|
|||||||
fn test_big_sb() {
|
fn test_big_sb() {
|
||||||
mut sb := strings.new_builder(100)
|
mut sb := strings.new_builder(100)
|
||||||
mut sb2 := strings.new_builder(10000)
|
mut sb2 := strings.new_builder(10000)
|
||||||
for i in 0..maxn {
|
for i in 0 .. maxn {
|
||||||
sb.writeln(i.str())
|
sb.writeln(i.str())
|
||||||
sb2.write('+')
|
sb2.write('+')
|
||||||
}
|
}
|
||||||
@ -62,12 +61,11 @@ fn test_big_sb() {
|
|||||||
assert lines[98765] == '98765'
|
assert lines[98765] == '98765'
|
||||||
println(sb2.len)
|
println(sb2.len)
|
||||||
assert sb2.len == maxn
|
assert sb2.len == maxn
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_byte_write() {
|
fn test_byte_write() {
|
||||||
mut sb := strings.new_builder(100)
|
mut sb := strings.new_builder(100)
|
||||||
temp_str := "byte testing"
|
temp_str := 'byte testing'
|
||||||
mut count := 0
|
mut count := 0
|
||||||
for word in temp_str {
|
for word in temp_str {
|
||||||
sb.write_b(word)
|
sb.write_b(word)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
module strings
|
module strings
|
||||||
|
|
||||||
// #-js
|
// #-js
|
||||||
// use levenshtein distance algorithm to calculate
|
// use levenshtein distance algorithm to calculate
|
||||||
// the distance between between two strings (lower is closer)
|
// the distance between between two strings (lower is closer)
|
||||||
pub fn levenshtein_distance(a string, b string) int {
|
pub fn levenshtein_distance(a string, b string) int {
|
||||||
mut f := [0].repeat(b.len + 1)
|
mut f := [0].repeat(b.len + 1)
|
||||||
for j in 0..f.len {
|
for j in 0 .. f.len {
|
||||||
f[j] = j
|
f[j] = j
|
||||||
}
|
}
|
||||||
for ca in a {
|
for ca in a {
|
||||||
@ -15,8 +16,7 @@ pub fn levenshtein_distance(a string, b string) int {
|
|||||||
mut mn := if f[j] + 1 <= f[j - 1] + 1 { f[j] + 1 } else { f[j - 1] + 1 }
|
mut mn := if f[j] + 1 <= f[j - 1] + 1 { f[j] + 1 } else { f[j - 1] + 1 }
|
||||||
if cb != ca {
|
if cb != ca {
|
||||||
mn = if mn <= fj1 + 1 { mn } else { fj1 + 1 }
|
mn = if mn <= fj1 + 1 { mn } else { fj1 + 1 }
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mn = if mn <= fj1 { mn } else { fj1 }
|
mn = if mn <= fj1 { mn } else { fj1 }
|
||||||
}
|
}
|
||||||
fj1 = f[j]
|
fj1 = f[j]
|
||||||
@ -50,14 +50,14 @@ pub fn dice_coefficient(s1 string, s2 string) f32 {
|
|||||||
}
|
}
|
||||||
a := if s1.len > s2.len { s1 } else { s2 }
|
a := if s1.len > s2.len { s1 } else { s2 }
|
||||||
b := if a == s1 { s2 } else { s1 }
|
b := if a == s1 { s2 } else { s1 }
|
||||||
mut first_bigrams := map[string]int
|
mut first_bigrams := map[string]int{}
|
||||||
for i in 0..a.len - 1 {
|
for i in 0 .. a.len - 1 {
|
||||||
bigram := a[i..i + 2]
|
bigram := a[i..i + 2]
|
||||||
q := if bigram in first_bigrams { first_bigrams[bigram] + 1 } else { 1 }
|
q := if bigram in first_bigrams { first_bigrams[bigram] + 1 } else { 1 }
|
||||||
first_bigrams[bigram] = q
|
first_bigrams[bigram] = q
|
||||||
}
|
}
|
||||||
mut intersection_size := 0
|
mut intersection_size := 0
|
||||||
for i in 0..b.len - 1 {
|
for i in 0 .. b.len - 1 {
|
||||||
bigram := b[i..i + 2]
|
bigram := b[i..i + 2]
|
||||||
count := if bigram in first_bigrams { first_bigrams[bigram] } else { 0 }
|
count := if bigram in first_bigrams { first_bigrams[bigram] } else { 0 }
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
@ -67,4 +67,3 @@ pub fn dice_coefficient(s1 string, s2 string) f32 {
|
|||||||
}
|
}
|
||||||
return (2.0 * f32(intersection_size)) / (f32(a.len) + f32(b.len) - 2)
|
return (2.0 * f32(intersection_size)) / (f32(a.len) + f32(b.len) - 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ pub fn repeat(c byte, n int) string {
|
|||||||
}
|
}
|
||||||
mut bytes := unsafe {malloc(n + 1)}
|
mut bytes := unsafe {malloc(n + 1)}
|
||||||
unsafe {
|
unsafe {
|
||||||
C.memset( bytes, c, n )
|
C.memset(bytes, c, n)
|
||||||
bytes[n] = `0`
|
bytes[n] = `0`
|
||||||
}
|
}
|
||||||
return unsafe { bytes.vstring_with_len(n) }
|
return unsafe {bytes.vstring_with_len(n)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// strings.repeat_string - gives you `n` repetitions of the substring `s`
|
// strings.repeat_string - gives you `n` repetitions of the substring `s`
|
||||||
@ -21,18 +21,18 @@ pub fn repeat_string(s string, n int) string {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
slen := s.len
|
slen := s.len
|
||||||
blen := slen*n
|
blen := slen * n
|
||||||
mut bytes := unsafe {malloc(blen + 1)}
|
mut bytes := unsafe {malloc(blen + 1)}
|
||||||
for bi in 0..n {
|
for bi in 0 .. n {
|
||||||
bislen := bi*slen
|
bislen := bi * slen
|
||||||
for si in 0..slen {
|
for si in 0 .. slen {
|
||||||
unsafe {
|
unsafe {
|
||||||
bytes[bislen+si] = s[si]
|
bytes[bislen + si] = s[si]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
bytes[blen] = `0`
|
bytes[blen] = `0`
|
||||||
}
|
}
|
||||||
return unsafe { bytes.vstring_with_len(blen) }
|
return unsafe {bytes.vstring_with_len(blen)}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,9 @@ pub fn repeat(c byte, n int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn repeat_string(s string, n int) string {
|
pub fn repeat_string(s string, n int) string {
|
||||||
/*
|
/*
|
||||||
// TODO: uncomment this. It is commented for now, so that `v doc strings` works
|
// TODO: uncomment this. It is commented for now, so that `v doc strings` works
|
||||||
res := # s.repeat(n)
|
res := # s.repeat(n)
|
||||||
return res
|
return res
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module strings
|
module strings
|
||||||
|
|
||||||
//import rand
|
// import rand
|
||||||
|
|
||||||
// random returns a random string with `n` characters
|
// random returns a random string with `n` characters
|
||||||
/*
|
/*
|
||||||
pub fn random(n int) string {
|
pub fn random(n int) string {
|
||||||
@ -12,4 +11,3 @@ pub fn random(n int) string {
|
|||||||
return tos(buf)
|
return tos(buf)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user