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

builtin: unsafe vlib pointer indexing (#5836)

This commit is contained in:
Nick Treleaven
2020-07-15 20:56:50 +01:00
committed by GitHub
parent cc7c8009a1
commit f5e6a83a05
7 changed files with 326 additions and 189 deletions

View File

@ -72,6 +72,7 @@ pub fn vstrlen(s byteptr) int {
// Converts a C string to a V string.
// String data is reused, not copied.
[unsafe_fn]
pub fn tos(s byteptr, len int) string {
// This should never happen.
if s == 0 {
@ -136,7 +137,9 @@ pub fn (a string) clone() string {
for i in 0..a.len {
b.str[i] = a.str[i]
}
b.str[a.len] = `\0`
unsafe {
b.str[a.len] = `\0`
}
return b
}
@ -149,10 +152,12 @@ pub fn (s string) cstr() byteptr {
// cstring_to_vstring creates a copy of cstr and turns it into a v string
pub fn cstring_to_vstring(cstr byteptr) string {
slen := C.strlen(charptr(cstr))
mut s := byteptr(memdup(cstr, slen + 1))
s[slen] = `\0`
return tos(s, slen)
unsafe {
slen := C.strlen(charptr(cstr))
mut s := byteptr(memdup(cstr, slen + 1))
s[slen] = `\0`
return tos(s, slen)
}
}
pub fn (s string) replace_once(rep, with string) string {
@ -193,7 +198,9 @@ pub fn (s string) replace(rep, with string) string {
if i == cur_idx {
// Reached the location of rep, replace it with "with"
for j in 0..with.len {
b[b_i] = with[j]
unsafe {
b[b_i] = with[j]
}
b_i++
}
// Skip the length of rep, since we just replaced it with "with"
@ -206,12 +213,16 @@ pub fn (s string) replace(rep, with string) string {
}
else {
// Rep doesnt start here, just copy
b[b_i] = s[i]
unsafe {
b[b_i] = s[i]
}
b_i++
}
}
b[new_len] = `\0`
return tos(b, new_len)
unsafe {
b[new_len] = `\0`
return tos(b, new_len)
}
}
struct RepIndex {
@ -292,7 +303,9 @@ pub fn (s string) replace_each(vals []string) string {
rep := vals[cur_idx.val_idx]
with := vals[cur_idx.val_idx + 1]
for j in 0..with.len {
b[b_i] = with[j]
unsafe {
b[b_i] = with[j]
}
b_i++
}
// Skip the length of rep, since we just replaced it with "with"
@ -305,12 +318,16 @@ pub fn (s string) replace_each(vals []string) string {
}
else {
// Rep doesnt start here, just copy
b[b_i] = s.str[i]
unsafe {
b[b_i] = s.str[i]
}
b_i++
}
}
b[new_len] = `\0`
return tos(b, new_len)
unsafe {
b[new_len] = `\0`
return tos(b, new_len)
}
}
pub fn (s string) bool() bool {
@ -411,12 +428,18 @@ fn (s string) add(a string) string {
len: new_len
}
for j in 0..s.len {
res.str[j] = s.str[j]
unsafe {
res.str[j] = s.str[j]
}
}
for j in 0..a.len {
res.str[s.len + j] = a.str[j]
unsafe {
res.str[s.len + j] = a.str[j]
}
}
unsafe {
res.str[new_len] = `\0` // V strings are not null terminated, but just in case
}
res.str[new_len] = `\0` // V strings are not null terminated, but just in case
return res
}
@ -448,10 +471,10 @@ pub fn (s string) split_nth(delim string, nth int) []string {
mut start := 0
nth_1 := nth - 1
for i <= s.len {
mut is_delim := s.str[i] == delim.str[0]
mut is_delim := unsafe {s.str[i] == delim.str[0]}
mut j := 0
for is_delim && j < delim.len {
is_delim = is_delim && s.str[i + j] == delim.str[j]
is_delim = is_delim && unsafe {s.str[i + j] == delim.str[j]}
j++
}
last := i == s.len - 1
@ -488,8 +511,8 @@ pub fn (s string) split_into_lines() []string {
}
mut start := 0
for i := 0; i < s.len; i++ {
is_lf := s.str[i] == `\n`
is_crlf := i != s.len - 1 && s.str[i] == `\r` && s.str[i + 1] == `\n`
is_lf := unsafe {s.str[i]} == `\n`
is_crlf := i != s.len - 1 && unsafe {s.str[i] == `\r` && s.str[i + 1] == `\n`}
is_eol := is_lf || is_crlf
is_last := if is_crlf {
i == s.len - 2
@ -549,16 +572,19 @@ pub fn (s string) substr(start, end int) string {
len: len
}
for i in 0..len {
res.str[i] = s.str[start + i]
unsafe {
res.str[i] = s.str[start + i]
}
}
unsafe {
res.str[len] = `\0`
}
res.str[len] = `\0`
/*
res := string {
str: s.str + start
len: len
}
*/
return res
}
@ -569,7 +595,7 @@ pub fn (s string) index_old(p string) int {
mut i := 0
for i < s.len {
mut j := 0
for j < p.len && s.str[i + j] == p.str[j] {
for j < p.len && unsafe {s.str[i + j] == p.str[j]} {
j++
}
if j == p.len {
@ -587,7 +613,7 @@ pub fn (s string) index(p string) ?int {
mut i := 0
for i < s.len {
mut j := 0
for j < p.len && s.str[i + j] == p.str[j] {
for j < p.len && unsafe {s.str[i + j] == p.str[j]} {
j++
}
if j == p.len {
@ -606,20 +632,20 @@ fn (s string) index_kmp(p string) int {
mut prefix := []int{len:p.len}
mut j := 0
for i := 1; i < p.len; i++ {
for p.str[j] != p.str[i] && j > 0 {
for unsafe {p.str[j] != p.str[i]} && j > 0 {
j = prefix[j - 1]
}
if p.str[j] == p.str[i] {
if unsafe {p.str[j] == p.str[i]} {
j++
}
prefix[i] = j
}
j = 0
for i in 0..s.len {
for p.str[j] != s.str[i] && j > 0 {
for unsafe {p.str[j] != s.str[i]} && j > 0 {
j = prefix[j - 1]
}
if p.str[j] == s.str[i] {
if unsafe {p.str[j] == s.str[i]} {
j++
}
if j == p.len {
@ -646,7 +672,7 @@ pub fn (s string) last_index(p string) ?int {
mut i := s.len - p.len
for i >= 0 {
mut j := 0
for j < p.len && s.str[i + j] == p.str[j] {
for j < p.len && unsafe {s.str[i + j] == p.str[j]} {
j++
}
if j == p.len {
@ -672,7 +698,7 @@ pub fn (s string) index_after(p string, start int) int {
for i < s.len {
mut j := 0
mut ii := i
for j < p.len && s.str[ii] == p.str[j] {
for j < p.len && unsafe {s.str[ii] == p.str[j]} {
j++
ii++
}
@ -686,7 +712,7 @@ pub fn (s string) index_after(p string, start int) int {
pub fn (s string) index_byte(c byte) int {
for i in 0..s.len {
if s.str[i] == c {
if unsafe {s.str[i]} == c {
return i
}
}
@ -695,7 +721,7 @@ pub fn (s string) index_byte(c byte) int {
pub fn (s string) last_index_byte(c byte) int {
for i := s.len - 1; i >= 0; i-- {
if s.str[i] == c {
if unsafe {s.str[i] == c} {
return i
}
}
@ -738,7 +764,7 @@ pub fn (s string) starts_with(p string) bool {
return false
}
for i in 0..p.len {
if s.str[i] != p.str[i] {
if unsafe {s.str[i] != p.str[i]} {
return false
}
}
@ -759,11 +785,13 @@ pub fn (s string) ends_with(p string) bool {
// TODO only works with ASCII
pub fn (s string) to_lower() string {
mut b := malloc(s.len + 1)
for i in 0..s.len {
b[i] = byte(C.tolower(s.str[i]))
unsafe {
mut b := malloc(s.len + 1)
for i in 0..s.len {
b[i] = byte(C.tolower(s.str[i]))
}
return tos(b, s.len)
}
return tos(b, s.len)
}
pub fn (s string) is_lower() bool {
@ -776,11 +804,13 @@ pub fn (s string) is_lower() bool {
}
pub fn (s string) to_upper() string {
mut b := malloc(s.len + 1)
for i in 0..s.len {
b[i] = byte(C.toupper(s.str[i]))
unsafe {
mut b := malloc(s.len + 1)
for i in 0..s.len {
b[i] = byte(C.toupper(s.str[i]))
}
return tos(b, s.len)
}
return tos(b, s.len)
}
pub fn (s string) is_upper() bool {
@ -996,7 +1026,7 @@ pub fn (s string) ustring() ustring {
runes: __new_array(0, s.len, int(sizeof(int)))
}
for i := 0; i < s.len; i++ {
char_len := utf8_char_len(s.str[i])
char_len := utf8_char_len(unsafe {s.str[i]})
res.runes << i
i += char_len - 1
res.len++
@ -1020,7 +1050,7 @@ pub fn (s string) ustring_tmp() ustring {
res.runes.len = s.len
mut j := 0
for i := 0; i < s.len; i++ {
char_len := utf8_char_len(s.str[i])
char_len := utf8_char_len(unsafe {s.str[i]})
res.runes[j] = i
j++
i += char_len - 1
@ -1063,14 +1093,14 @@ pub fn (u ustring) add(a ustring) ustring {
}
mut j := 0
for i := 0; i < u.s.len; i++ {
char_len := utf8_char_len(u.s.str[i])
char_len := utf8_char_len(unsafe {u.s.str[i]})
res.runes << j
i += char_len - 1
j += char_len
res.len++
}
for i := 0; i < a.s.len; i++ {
char_len := utf8_char_len(a.s.str[i])
char_len := utf8_char_len(unsafe {a.s.str[i]})
res.runes << j
i += char_len - 1
j += char_len
@ -1157,7 +1187,9 @@ fn (s string) at(idx int) byte {
panic('string index out of range: $idx / $s.len')
}
}
return s.str[idx]
unsafe {
return s.str[idx]
}
}
pub fn (u ustring) at(idx int) string {
@ -1279,18 +1311,24 @@ pub fn (a []string) join(del string) string {
// Go thru every string and copy its every char one by one
for i, val in a {
for j in 0..val.len {
res.str[idx] = val.str[j]
unsafe {
res.str[idx] = val.str[j]
}
idx++
}
// Add del if it's not last
if i != a.len - 1 {
for k in 0..del.len {
res.str[idx] = del.str[k]
unsafe {
res.str[idx] = del.str[k]
}
idx++
}
}
}
res.str[res.len] = `\0`
unsafe {
res.str[res.len] = `\0`
}
return res
}
@ -1308,7 +1346,9 @@ pub fn (s string) reverse() string {
len: s.len
}
for i := s.len - 1; i >= 0; i-- {
res.str[s.len - i - 1] = s[i]
unsafe {
res.str[s.len - i - 1] = s[i]
}
}
return res
}
@ -1362,10 +1402,14 @@ pub fn (s string) repeat(count int) string {
mut ret := malloc(s.len * count + 1)
for i in 0 .. count {
for j in 0 .. s.len {
ret[i * s.len + j] = s[j]
unsafe {
ret[i * s.len + j] = s[j]
}
}
}
ret[s.len * count] = 0
unsafe {
ret[s.len * count] = 0
}
return string(ret)
}
@ -1375,11 +1419,13 @@ pub fn (s string) fields() []string {
}
pub fn (s string) map(func fn(byte) byte) string {
mut res := malloc(s.len + 1)
for i in 0..s.len {
res[i] = func(s[i])
unsafe {
mut res := malloc(s.len + 1)
for i in 0..s.len {
res[i] = func(s[i])
}
return tos(res, s.len)
}
return tos(res, s.len)
}
pub fn (s string) filter(func fn(b byte) bool) string {
@ -1425,11 +1471,15 @@ pub fn (s string) strip_margin_custom(del byte) string {
mut count := 0
for i := 0; i < s.len; i++ {
if s[i] in [`\n`, `\r`] {
ret[count] = s[i]
unsafe {
ret[count] = s[i]
}
count++
// CRLF
if s[i] == `\r` && i < s.len - 1 && s[i+1] == `\n` {
ret[count] = s[i+1]
unsafe {
ret[count] = s[i+1]
}
count++
i++
}
@ -1441,10 +1491,14 @@ pub fn (s string) strip_margin_custom(del byte) string {
}
}
} else {
ret[count] = s[i]
unsafe {
ret[count] = s[i]
}
count++
}
}
ret[count] = 0
unsafe {
ret[count] = 0
}
return string(ret)
}