builtin: unsafe vlib pointer indexing (#5836)

pull/5842/head
Nick Treleaven 2020-07-15 20:56:50 +01:00 committed by GitHub
parent cc7c8009a1
commit f5e6a83a05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 326 additions and 189 deletions

View File

@ -488,12 +488,18 @@ pub fn (b []byte) hex() string {
mut dst_i := 0 mut dst_i := 0
for i in b { for i in b {
n0 := i >> 4 n0 := i >> 4
hex[dst_i++] = if n0 < 10 { n0 + `0` } else { n0 + byte(87) } unsafe {
hex[dst_i++] = if n0 < 10 { n0 + `0` } else { n0 + byte(87) }
}
n1 := i & 0xF n1 := i & 0xF
hex[dst_i++] = if n1 < 10 { n1 + `0` } else { n1 + byte(87) } unsafe {
hex[dst_i++] = if n1 < 10 { n1 + `0` } else { n1 + byte(87) }
}
}
unsafe {
hex[dst_i] = `\0`
return tos(hex,dst_i)
} }
hex[dst_i] = `\0`
return tos(hex,dst_i)
} }
// copy copies the `src` byte array elements to the `dst` byte array. // copy copies the `src` byte array elements to the `dst` byte array.

View File

@ -72,13 +72,17 @@ pub fn (nn int) str_l(max int) string {
} }
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
n1 := n / 100 n1 := n / 100
d = ((n - (n1 * 100)) << 1) d = ((n - (n1 * 100)) << 1)
n = n1 n = n1
buf[index--] = digit_pairs.str[d++] unsafe {
buf[index--] = digit_pairs.str[d] buf[index--] = digit_pairs.str[d++]
buf[index--] = digit_pairs.str[d]
}
} }
index++ index++
@ -90,13 +94,15 @@ pub fn (nn int) str_l(max int) string {
// Prepend - if it's negative // Prepend - if it's negative
if is_neg { if is_neg {
index-- index--
buf[index] = `-` unsafe {
buf[index] = `-`
}
} }
unsafe { unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
return tos(buf, (max-index))
} }
return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -126,13 +132,17 @@ pub fn (nn u32) str() string {
mut buf := malloc(max + 1) mut buf := malloc(max + 1)
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
n1 := n / u32(100) n1 := n / u32(100)
d = ((n - (n1 * u32(100))) << u32(1)) d = ((n - (n1 * u32(100))) << u32(1))
n = n1 n = n1
buf[index--] = digit_pairs[d++] unsafe {
buf[index--] = digit_pairs[d] buf[index--] = digit_pairs[d++]
buf[index--] = digit_pairs[d]
}
} }
index++ index++
@ -143,8 +153,8 @@ pub fn (nn u32) str() string {
unsafe { unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
return tos(buf, (max-index))
} }
return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -169,13 +179,17 @@ pub fn (nn i64) str() string {
} }
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
n1 := n / i64(100) n1 := n / i64(100)
d = ((n - (n1 * i64(100))) << i64(1)) d = ((n - (n1 * i64(100))) << i64(1))
n = n1 n = n1
buf[index--] = digit_pairs[d++] unsafe {
buf[index--] = digit_pairs[d] buf[index--] = digit_pairs[d++]
buf[index--] = digit_pairs[d]
}
} }
index++ index++
@ -187,13 +201,15 @@ pub fn (nn i64) str() string {
// Prepend - if it's negative // Prepend - if it's negative
if is_neg { if is_neg {
index-- index--
buf[index] = `-` unsafe {
buf[index] = `-`
}
} }
unsafe { unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
return tos(buf, (max-index))
} }
return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -207,13 +223,17 @@ pub fn (nn u64) str() string {
mut buf := vcalloc(max + 1) mut buf := vcalloc(max + 1)
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
n1 := n / 100 n1 := n / 100
d = ((n - (n1 * 100)) << 1) d = ((n - (n1 * 100)) << 1)
n = n1 n = n1
buf[index--] = digit_pairs[d++] unsafe {
buf[index--] = digit_pairs[d] buf[index--] = digit_pairs[d++]
buf[index--] = digit_pairs[d]
}
} }
index++ index++
@ -224,8 +244,8 @@ pub fn (nn u64) str() string {
unsafe { unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
return tos(buf, (max-index))
} }
return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -258,11 +278,15 @@ pub fn (nn byte) hex() string {
mut buf := malloc(max + 1) mut buf := malloc(max + 1)
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
d := n & 0xF d := n & 0xF
n = n >> 4 n = n >> 4
buf[index--] = if d < 10 { d + `0` } else { d + 87 } unsafe {
buf[index--] = if d < 10 { d + `0` } else { d + 87 }
}
} }
//buf[index--] = `x` //buf[index--] = `x`
//buf[index] = `0` //buf[index] = `0`
@ -287,11 +311,15 @@ pub fn (nn u16) hex() string {
mut buf := malloc(max + 1) mut buf := malloc(max + 1)
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
d := byte(n & 0xF) d := byte(n & 0xF)
n = n >> 4 n = n >> 4
buf[index--] = if d < 10 { d + `0` } else { d + 87 } unsafe {
buf[index--] = if d < 10 { d + `0` } else { d + 87 }
}
} }
//buf[index--] = `x` //buf[index--] = `x`
//buf[index] = `0` //buf[index] = `0`
@ -316,11 +344,15 @@ pub fn (nn u32) hex() string {
mut buf := malloc(max + 1) mut buf := malloc(max + 1)
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
d := byte(n & 0xF) d := byte(n & 0xF)
n = n >> 4 n = n >> 4
buf[index--] = if d < 10 { d + `0` } else { d + 87 } unsafe {
buf[index--] = if d < 10 { d + `0` } else { d + 87 }
}
} }
//buf[index--] = `x` //buf[index--] = `x`
//buf[index] = `0` //buf[index] = `0`
@ -349,11 +381,15 @@ pub fn (nn u64) hex() string {
mut buf := malloc(max + 1) mut buf := malloc(max + 1)
mut index := max mut index := max
buf[index--] = `\0` unsafe {
buf[index--] = `\0`
}
for n > 0 { for n > 0 {
d := byte(n & 0xF) d := byte(n & 0xF)
n = n >> 4 n = n >> 4
buf[index--] = if d < 10 { d + `0` } else { d + 87 } unsafe {
buf[index--] = if d < 10 { d + `0` } else { d + 87 }
}
} }
//buf[index--] = `x` //buf[index--] = `x`
//buf[index] = `0` //buf[index] = `0`
@ -361,8 +397,8 @@ pub fn (nn u64) hex() string {
unsafe { unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
return tos(buf, (max-index))
} }
return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -405,8 +441,10 @@ pub fn (c byte) str() string {
str: malloc(2) str: malloc(2)
len: 1 len: 1
} }
str.str[0] = c unsafe {
str.str[1] = `\0` str.str[0] = c
str.str[1] = `\0`
}
return str return str
} }

View File

@ -120,12 +120,14 @@ fn new_dense_array(value_bytes int) DenseArray {
fn (mut d DenseArray) push(key string, value voidptr) u32 { fn (mut d DenseArray) push(key string, value voidptr) u32 {
if d.cap == d.len { if d.cap == d.len {
d.cap += d.cap >> 3 d.cap += d.cap >> 3
d.keys = &string(v_realloc(d.keys, sizeof(string) * d.cap)) unsafe {
d.values = v_realloc(d.values, u32(d.value_bytes) * d.cap) d.keys = &string(v_realloc(d.keys, sizeof(string) * d.cap))
d.values = v_realloc(d.values, u32(d.value_bytes) * d.cap)
}
} }
push_index := d.len push_index := d.len
d.keys[push_index] = key
unsafe { unsafe {
d.keys[push_index] = key
C.memcpy(d.values + push_index * u32(d.value_bytes), value, d.value_bytes) C.memcpy(d.values + push_index * u32(d.value_bytes), value, d.value_bytes)
} }
d.len++ d.len++
@ -148,11 +150,13 @@ fn (mut d DenseArray) zeros_to_end() {
mut tmp_value := malloc(d.value_bytes) mut tmp_value := malloc(d.value_bytes)
mut count := u32(0) mut count := u32(0)
for i in 0 .. d.len { for i in 0 .. d.len {
if d.keys[i].str != 0 { if unsafe {d.keys[i]}.str != 0 {
// swap keys // swap keys
tmp_key := d.keys[count] unsafe {
d.keys[count] = d.keys[i] tmp_key := d.keys[count]
d.keys[i] = tmp_key d.keys[count] = d.keys[i]
d.keys[i] = tmp_key
}
// swap values (TODO: optimize) // swap values (TODO: optimize)
unsafe { unsafe {
C.memcpy(tmp_value, d.values + count * u32(d.value_bytes), d.value_bytes) C.memcpy(tmp_value, d.values + count * u32(d.value_bytes), d.value_bytes)
@ -166,8 +170,10 @@ fn (mut d DenseArray) zeros_to_end() {
d.deletes = 0 d.deletes = 0
d.len = count d.len = count
d.cap = if count < 8 { u32(8) } else { count } d.cap = if count < 8 { u32(8) } else { count }
d.keys = &string(v_realloc(d.keys, sizeof(string) * d.cap)) unsafe {
d.values = v_realloc(d.values, u32(d.value_bytes) * d.cap) d.keys = &string(v_realloc(d.keys, sizeof(string) * d.cap))
d.values = v_realloc(d.values, u32(d.value_bytes) * d.cap)
}
} }
pub struct map { pub struct map {
@ -229,7 +235,7 @@ fn (m &map) key_to_index(key string) (u32,u32) {
fn (m &map) meta_less(_index u32, _metas u32) (u32,u32) { fn (m &map) meta_less(_index u32, _metas u32) (u32,u32) {
mut index := _index mut index := _index
mut meta := _metas mut meta := _metas
for meta < m.metas[index] { for meta < unsafe {m.metas[index]} {
index += 2 index += 2
meta += probe_inc meta += probe_inc
} }
@ -241,20 +247,26 @@ fn (mut m map) meta_greater(_index u32, _metas u32, kvi u32) {
mut meta := _metas mut meta := _metas
mut index := _index mut index := _index
mut kv_index := kvi mut kv_index := kvi
for m.metas[index] != 0 { for unsafe {m.metas[index]} != 0 {
if meta > m.metas[index] { if meta > unsafe {m.metas[index]} {
tmp_meta := m.metas[index] unsafe {
m.metas[index] = meta tmp_meta := m.metas[index]
meta = tmp_meta m.metas[index] = meta
tmp_index := m.metas[index + 1] meta = tmp_meta
m.metas[index + 1] = kv_index }
tmp_index := unsafe {m.metas[index + 1]}
unsafe {
m.metas[index + 1] = kv_index
}
kv_index = tmp_index kv_index = tmp_index
} }
index += 2 index += 2
meta += probe_inc meta += probe_inc
} }
m.metas[index] = meta unsafe {
m.metas[index + 1] = kv_index m.metas[index] = meta
m.metas[index + 1] = kv_index
}
probe_count := (meta >> hashbits) - 1 probe_count := (meta >> hashbits) - 1
m.ensure_extra_metas(probe_count) m.ensure_extra_metas(probe_count)
} }
@ -287,9 +299,9 @@ fn (mut m map) set(k string, value voidptr) {
mut index,mut meta := m.key_to_index(key) mut index,mut meta := m.key_to_index(key)
index,meta = m.meta_less(index, meta) index,meta = m.meta_less(index, meta)
// While we might have a match // While we might have a match
for meta == m.metas[index] { for meta == unsafe {m.metas[index]} {
kv_index := m.metas[index + 1] kv_index := unsafe {m.metas[index + 1]}
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, unsafe {m.key_values.keys[kv_index]}) {
unsafe { unsafe {
C.memcpy(m.key_values.values + kv_index * u32(m.value_bytes), value, m.value_bytes) C.memcpy(m.key_values.values + kv_index * u32(m.value_bytes), value, m.value_bytes)
} }
@ -326,13 +338,15 @@ fn (mut m map) expand() {
// the max_load_factor in an operation. // the max_load_factor in an operation.
fn (mut m map) rehash() { fn (mut m map) rehash() {
meta_bytes := sizeof(u32) * (m.cap + 2 + m.extra_metas) meta_bytes := sizeof(u32) * (m.cap + 2 + m.extra_metas)
m.metas = &u32(v_realloc(m.metas, meta_bytes)) unsafe {
C.memset(m.metas, 0, meta_bytes) m.metas = &u32(v_realloc(m.metas, meta_bytes))
C.memset(m.metas, 0, meta_bytes)
}
for i := u32(0); i < m.key_values.len; i++ { for i := u32(0); i < m.key_values.len; i++ {
if m.key_values.keys[i].str == 0 { if unsafe {m.key_values.keys[i]}.str == 0 {
continue continue
} }
mut index,mut meta := m.key_to_index(m.key_values.keys[i]) mut index,mut meta := m.key_to_index(unsafe {m.key_values.keys[i]})
index,meta = m.meta_less(index, meta) index,meta = m.meta_less(index, meta)
m.meta_greater(index, meta, i) m.meta_greater(index, meta, i)
} }
@ -345,16 +359,16 @@ fn (mut m map) cached_rehash(old_cap u32) {
m.metas = &u32(vcalloc(int(sizeof(u32) * (m.cap + 2 + m.extra_metas)))) m.metas = &u32(vcalloc(int(sizeof(u32) * (m.cap + 2 + m.extra_metas))))
old_extra_metas := m.extra_metas old_extra_metas := m.extra_metas
for i := u32(0); i <= old_cap + old_extra_metas; i += 2 { for i := u32(0); i <= old_cap + old_extra_metas; i += 2 {
if old_metas[i] == 0 { if unsafe {old_metas[i]} == 0 {
continue continue
} }
old_meta := old_metas[i] old_meta := unsafe {old_metas[i]}
old_probe_count := ((old_meta >> hashbits) - 1) << 1 old_probe_count := ((old_meta >> hashbits) - 1) << 1
old_index := (i - old_probe_count) & (m.cap >> 1) old_index := (i - old_probe_count) & (m.cap >> 1)
mut index := (old_index | (old_meta << m.shift)) & m.cap mut index := (old_index | (old_meta << m.shift)) & m.cap
mut meta := (old_meta & hash_mask) | probe_inc mut meta := (old_meta & hash_mask) | probe_inc
index,meta = m.meta_less(index, meta) index,meta = m.meta_less(index, meta)
kv_index := old_metas[i + 1] kv_index := unsafe {old_metas[i + 1]}
m.meta_greater(index, meta, kv_index) m.meta_greater(index, meta, kv_index)
} }
unsafe{ unsafe{
@ -369,9 +383,9 @@ fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
for { for {
mut index,mut meta := m.key_to_index(key) mut index,mut meta := m.key_to_index(key)
for { for {
if meta == m.metas[index] { if meta == unsafe {m.metas[index]} {
kv_index := m.metas[index + 1] kv_index := unsafe {m.metas[index + 1]}
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, unsafe {m.key_values.keys[kv_index]}) {
unsafe { unsafe {
return voidptr(m.key_values.values + kv_index * u32(m.value_bytes)) return voidptr(m.key_values.values + kv_index * u32(m.value_bytes))
} }
@ -379,7 +393,7 @@ fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
} }
index += 2 index += 2
meta += probe_inc meta += probe_inc
if meta > m.metas[index] { break } if meta > unsafe {m.metas[index]} { break }
} }
// Key not found, insert key with zero-value // Key not found, insert key with zero-value
m.set(key, zero) m.set(key, zero)
@ -392,9 +406,9 @@ fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
fn (m map) get(key string, zero voidptr) voidptr { fn (m map) get(key string, zero voidptr) voidptr {
mut index,mut meta := m.key_to_index(key) mut index,mut meta := m.key_to_index(key)
for { for {
if meta == m.metas[index] { if meta == unsafe {m.metas[index]} {
kv_index := m.metas[index + 1] kv_index := unsafe {m.metas[index + 1]}
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, unsafe {m.key_values.keys[kv_index]}) {
unsafe { unsafe {
return voidptr(m.key_values.values + kv_index * u32(m.value_bytes)) return voidptr(m.key_values.values + kv_index * u32(m.value_bytes))
} }
@ -402,7 +416,7 @@ fn (m map) get(key string, zero voidptr) voidptr {
} }
index += 2 index += 2
meta += probe_inc meta += probe_inc
if meta > m.metas[index] { break } if meta > unsafe {m.metas[index]} { break }
} }
return zero return zero
} }
@ -411,15 +425,15 @@ fn (m map) get(key string, zero voidptr) voidptr {
fn (m map) exists(key string) bool { fn (m map) exists(key string) bool {
mut index,mut meta := m.key_to_index(key) mut index,mut meta := m.key_to_index(key)
for { for {
if meta == m.metas[index] { if meta == unsafe {m.metas[index]} {
kv_index := m.metas[index + 1] kv_index := unsafe {m.metas[index + 1]}
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, unsafe {m.key_values.keys[kv_index]}) {
return true return true
} }
} }
index += 2 index += 2
meta += probe_inc meta += probe_inc
if meta > m.metas[index] { break } if meta > unsafe {m.metas[index]} { break }
} }
return false return false
} }
@ -429,20 +443,26 @@ pub fn (mut m map) delete(key string) {
mut index,mut meta := m.key_to_index(key) mut index,mut meta := m.key_to_index(key)
index,meta = m.meta_less(index, meta) index,meta = m.meta_less(index, meta)
// Perform backwards shifting // Perform backwards shifting
for meta == m.metas[index] { for meta == unsafe {m.metas[index]} {
kv_index := m.metas[index + 1] kv_index := unsafe {m.metas[index + 1]}
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, unsafe {m.key_values.keys[kv_index]}) {
for (m.metas[index + 2] >> hashbits) > 1 { for (unsafe {m.metas[index + 2]} >> hashbits) > 1 {
m.metas[index] = m.metas[index + 2] - probe_inc unsafe {
m.metas[index + 1] = m.metas[index + 3] m.metas[index] = m.metas[index + 2] - probe_inc
m.metas[index + 1] = m.metas[index + 3]
}
index += 2 index += 2
} }
m.len-- m.len--
m.metas[index] = 0 unsafe {
m.metas[index] = 0
}
m.key_values.deletes++ m.key_values.deletes++
// Mark key as deleted // Mark key as deleted
m.key_values.keys[kv_index].free() unsafe {
C.memset(&m.key_values.keys[kv_index], 0, sizeof(string)) m.key_values.keys[kv_index].free()
C.memset(&m.key_values.keys[kv_index], 0, sizeof(string))
}
if m.key_values.len <= 32 { if m.key_values.len <= 32 {
return return
} }
@ -465,10 +485,10 @@ pub fn (m &map) keys() []string {
mut keys := []string{ len:m.len } mut keys := []string{ len:m.len }
mut j := 0 mut j := 0
for i := u32(0); i < m.key_values.len; i++ { for i := u32(0); i < m.key_values.len; i++ {
if m.key_values.keys[i].str == 0 { if unsafe {m.key_values.keys[i]}.str == 0 {
continue continue
} }
keys[j] = m.key_values.keys[i].clone() keys[j] = unsafe {m.key_values.keys[i]}.clone()
j++ j++
} }
return keys return keys
@ -502,21 +522,29 @@ pub fn (m map) clone() map {
extra_metas: m.extra_metas extra_metas: m.extra_metas
len: m.len len: m.len
} }
C.memcpy(res.metas, m.metas, metas_size) unsafe {
C.memcpy(res.metas, m.metas, metas_size)
}
return res return res
} }
[unsafe_fn] [unsafe_fn]
pub fn (m &map) free() { pub fn (m &map) free() {
free(m.metas) unsafe {
free(m.metas)
}
for i := u32(0); i < m.key_values.len; i++ { for i := u32(0); i < m.key_values.len; i++ {
if m.key_values.keys[i].str == 0 { if unsafe {m.key_values.keys[i]}.str == 0 {
continue continue
} }
m.key_values.keys[i].free() unsafe {
m.key_values.keys[i].free()
}
}
unsafe {
free(m.key_values.keys)
free(m.key_values.values)
} }
free(m.key_values.keys)
free(m.key_values.values)
} }
pub fn (m map_string) str() string { pub fn (m map_string) str() string {

View File

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

View File

@ -48,7 +48,7 @@ fn wyhash64(key byteptr, len, seed_ u64) u64 {
if len == 0 { if len == 0 {
return 0 return 0
} }
mut p := &key[0] mut p := key
mut seed := seed_ mut seed := seed_
mut i := len & 63 mut i := len & 63
unsafe { unsafe {
@ -119,15 +119,21 @@ pub fn wymum(a, b u64) u64 {
[inline] [inline]
fn wyr3(p byteptr, k u64) u64 { fn wyr3(p byteptr, k u64) u64 {
return (u64(p[0])<<16) | (u64(p[k>>1])<<8) | u64(p[k - 1]) unsafe {
return (u64(p[0])<<16) | (u64(p[k>>1])<<8) | u64(p[k - 1])
}
} }
[inline] [inline]
fn wyr4(p byteptr) u64 { fn wyr4(p byteptr) u64 {
return u32(p[0]) | (u32(p[1])<<u32(8)) | (u32(p[2])<<u32(16)) | (u32(p[3])<<u32(24)) unsafe {
return u32(p[0]) | (u32(p[1])<<u32(8)) | (u32(p[2])<<u32(16)) | (u32(p[3])<<u32(24))
}
} }
[inline] [inline]
fn wyr8(p byteptr) u64 { fn wyr8(p byteptr) u64 {
return u64(p[0]) | (u64(p[1])<<8) | (u64(p[2])<<16) | (u64(p[3])<<24) | (u64(p[4])<<32) | (u64(p[5])<<40) | (u64(p[6])<<48) | (u64(p[7])<<56) unsafe {
return u64(p[0]) | (u64(p[1])<<8) | (u64(p[2])<<16) | (u64(p[3])<<24) | (u64(p[4])<<32) | (u64(p[5])<<40) | (u64(p[6])<<48) | (u64(p[7])<<56)
}
} }

View File

@ -384,7 +384,7 @@ pub fn remove_tail_zeros(s string) string {
mut in_decimal := false mut in_decimal := false
mut prev_ch := byte(0) mut prev_ch := byte(0)
for i < s.len { for i < s.len {
ch := s.str[i] ch := unsafe {s.str[i]}
if ch == `.` { if ch == `.` {
in_decimal = true in_decimal = true
dot_pos = i dot_pos = i
@ -405,14 +405,14 @@ pub fn remove_tail_zeros(s string) string {
mut tmp := "" mut tmp := ""
if last_zero_start > 0 { if last_zero_start > 0 {
if last_zero_start == dot_pos+1 { if last_zero_start == dot_pos+1 {
tmp = s[..dot_pos] + s [i..] tmp = s[..dot_pos] + s[i..]
}else { }else {
tmp = s[..last_zero_start] + s [i..] tmp = s[..last_zero_start] + s[i..]
} }
} else { } else {
tmp = s tmp = s
} }
if tmp.str[tmp.len-1] == `.` { if unsafe {tmp.str[tmp.len-1]} == `.` {
return tmp[..tmp.len-1] return tmp[..tmp.len-1]
} }
return tmp return tmp
@ -474,7 +474,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// single char, manage it here // single char, manage it here
if ch == `c` && status == .field_char { if ch == `c` && status == .field_char {
d1 := *(&byte(pt[p_index])) d1 := unsafe {*(&byte(pt[p_index]))}
res.write_b(d1) res.write_b(d1)
status = .reset_params status = .reset_params
p_index++ p_index++
@ -484,7 +484,8 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// pointer, manage it here // pointer, manage it here
if ch == `p` && status == .field_char { if ch == `p` && status == .field_char {
res.write("0x"+ptr_str(pt[p_index])) res.write("0x")
res.write(ptr_str(unsafe {pt[p_index]}))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
@ -525,9 +526,9 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
// manage "%.*s" precision field // manage "%.*s" precision field
else if ch == `.` && fc_ch1 == `*` && fc_ch2 == `s` { else if ch == `.` && fc_ch1 == `*` && fc_ch2 == `s` {
len := *(&int(pt[p_index])) len := unsafe {*(&int(pt[p_index]))}
p_index++ p_index++
mut s := *(&string(pt[p_index])) mut s := unsafe {*(&string(pt[p_index]))}
s = s[..len] s = s[..len]
p_index++ p_index++
res.write(s) res.write(s)
@ -629,11 +630,11 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// hh fot 8 bit int // hh fot 8 bit int
`h` { `h` {
if ch2 == `h` { if ch2 == `h` {
x := *(&i8(pt[p_index])) x := unsafe {*(&i8(pt[p_index]))}
positive = if x >= 0 { true } else { false } positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) } d1 = if positive { u64(x) } else { u64(-x) }
} else { } else {
x := *(&i16(pt[p_index])) x := unsafe {*(&i16(pt[p_index]))}
positive = if x >= 0 { true } else { false } positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) } d1 = if positive { u64(x) } else { u64(-x) }
} }
@ -653,13 +654,13 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
d1 = if positive { u64(x) } else { u64(-x) } d1 = if positive { u64(x) } else { u64(-x) }
} }
*/ */
x := *(&i64(pt[p_index])) x := unsafe {*(&i64(pt[p_index]))}
positive = if x >= 0 { true } else { false } positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) } d1 = if positive { u64(x) } else { u64(-x) }
} }
// defualt int // default int
else { else {
x := *(&int(pt[p_index])) x := unsafe {*(&int(pt[p_index]))}
positive = if x >= 0 { true } else { false } positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) } d1 = if positive { u64(x) } else { u64(-x) }
} }
@ -685,9 +686,9 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// hh fot 8 bit unsigned int // hh fot 8 bit unsigned int
`h` { `h` {
if ch2 == `h` { if ch2 == `h` {
d1 = u64(*(&byte(pt[p_index]))) d1 = u64(unsafe {*(&byte(pt[p_index]))})
} else { } else {
d1 = u64(*(&u16(pt[p_index]))) d1 = u64(unsafe {*(&u16(pt[p_index]))})
} }
} }
// l u64 // l u64
@ -701,11 +702,11 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
d1 = u64(*(&u64(pt[p_index]))) d1 = u64(*(&u64(pt[p_index])))
} }
*/ */
d1 = u64(*(&u64(pt[p_index]))) d1 = u64(unsafe {*(&u64(pt[p_index]))})
} }
// defualt int // defualt int
else { else {
d1 = u64(*(&u32(pt[p_index]))) d1 = u64(unsafe {*(&u32(pt[p_index]))})
} }
} }
@ -725,10 +726,10 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// hh fot 8 bit int // hh fot 8 bit int
`h` { `h` {
if ch2 == `h` { if ch2 == `h` {
x := *(&i8(pt[p_index])) x := unsafe {*(&i8(pt[p_index]))}
s = x.hex() s = x.hex()
} else { } else {
x := *(&i16(pt[p_index])) x := unsafe {*(&i16(pt[p_index]))}
s = x.hex() s = x.hex()
} }
} }
@ -745,11 +746,11 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
s = x.hex() s = x.hex()
} }
*/ */
x := *(&i64(pt[p_index])) x := unsafe {*(&i64(pt[p_index]))}
s = x.hex() s = x.hex()
} }
else { else {
x := *(&int(pt[p_index])) x := unsafe {*(&int(pt[p_index]))}
s = x.hex() s = x.hex()
} }
} }
@ -767,7 +768,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// float and double // float and double
if ch in [`f`, `F`] { if ch in [`f`, `F`] {
x := *(&f64(pt[p_index])) x := unsafe {*(&f64(pt[p_index]))}
mut positive := x >= f64(0.0) mut positive := x >= f64(0.0)
len1 = if len1 >= 0 { len1 } else { def_len1 } len1 = if len1 >= 0 { len1 } else { def_len1 }
s := format_fl(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign}) s := format_fl(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
@ -778,7 +779,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
continue continue
} }
else if ch in [`e`, `E`] { else if ch in [`e`, `E`] {
x := *(&f64(pt[p_index])) x := unsafe {*(&f64(pt[p_index]))}
mut positive := x >= f64(0.0) mut positive := x >= f64(0.0)
len1 = if len1 >= 0 { len1 } else { def_len1 } len1 = if len1 >= 0 { len1 } else { def_len1 }
s := format_es(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign}) s := format_es(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
@ -789,7 +790,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
continue continue
} }
else if ch in [`g`, `G`] { else if ch in [`g`, `G`] {
x := *(&f64(pt[p_index])) x := unsafe {*(&f64(pt[p_index]))}
mut positive := x >= f64(0.0) mut positive := x >= f64(0.0)
mut s := "" mut s := ""
tx := fabs(x) tx := fabs(x)
@ -810,7 +811,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// string // string
else if ch == `s` { else if ch == `s` {
s1 := *(&string(pt[p_index])) s1 := unsafe{*(&string(pt[p_index]))}
pad_ch = ` ` pad_ch = ` `
res.write(format_str(s1, {pad_ch: pad_ch, len0: len0, len1: 0, positive: true, sign_flag: false, allign: allign})) res.write(format_str(s1, {pad_ch: pad_ch, len0: len0, len1: 0, positive: true, sign_flag: false, allign: allign}))
status = .reset_params status = .reset_params

View File

@ -5,10 +5,11 @@ pub fn repeat(c byte, n int) string {
if n <= 0 { if n <= 0 {
return '' return ''
} }
mut bytes := &byte(0) mut bytes := unsafe {malloc(n + 1)}
unsafe { bytes = malloc(n + 1) } unsafe {
C.memset( bytes, c, n ) C.memset( bytes, c, n )
bytes[n] = `0` bytes[n] = `0`
}
return string( bytes, n ) return string( bytes, n )
} }
@ -21,14 +22,17 @@ pub fn repeat_string(s string, n int) string {
} }
slen := s.len slen := s.len
blen := slen*n blen := slen*n
mut bytes := &byte(0) mut bytes := unsafe {malloc(blen + 1)}
unsafe { bytes = 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 {
bytes[bislen+si] = s[si] unsafe {
bytes[bislen+si] = s[si]
}
} }
} }
bytes[blen] = `0` unsafe {
bytes[blen] = `0`
}
return string( bytes, blen ) return string( bytes, blen )
} }