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

vlib/arrays: fix copy to not use memcpy for array, map, string (#13703)

This commit is contained in:
Nick Treleaven 2022-03-09 22:30:51 +00:00 committed by GitHub
parent de2fc87995
commit 4bea35b028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 1 deletions

View File

@ -546,9 +546,27 @@ fn swap_nonoverlapping<T>(x_ &T, y_ &T, count int) {
// Returns the number of elements copied. // Returns the number of elements copied.
pub fn copy<T>(mut dst []T, src []T) int { pub fn copy<T>(mut dst []T, src []T) int {
min := if dst.len < src.len { dst.len } else { src.len } min := if dst.len < src.len { dst.len } else { src.len }
if min > 0 { if min <= 0 {
return 0
}
if can_copy_bits<T>() {
blen := min * int(sizeof(T)) blen := min * int(sizeof(T))
unsafe { vmemmove(&T(dst.data), src.data, blen) } unsafe { vmemmove(&T(dst.data), src.data, blen) }
} else {
for i in 0 .. min {
dst[i] = src[i]
}
} }
return min return min
} }
// determines if T can be copied using `memcpy`
// false if autofree needs to intervene
// false if type is not copyable e.g. map
fn can_copy_bits<T>() bool {
// references, C pointers, integers, floats, runes
if T.name[0] in [`&`, `b`, `c`, `f`, `i`, `r`, `u`, `v`] {
return true
}
return false
}

View File

@ -281,3 +281,15 @@ fn test_copy() {
assert copy(mut b, [8, 9]) == 2 assert copy(mut b, [8, 9]) == 2
assert b == [8, 9, 3, 7] assert b == [8, 9, 3, 7]
} }
fn test_can_copy_bits() {
assert can_copy_bits<byte>()
assert can_copy_bits<int>()
assert can_copy_bits<voidptr>()
assert can_copy_bits<&byte>()
// autofree needs to intercept assign
assert !can_copy_bits<string>()
assert !can_copy_bits<[]int>()
// map not copyable
assert !can_copy_bits<map[string]int>()
}