v/checker: Warn about pointer indexing outside unsafe {} (#5918)
parent
d46a89b90d
commit
ee349691f9
|
@ -86,7 +86,7 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
||||||
//////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
|
//////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
|
||||||
csymbols := C.backtrace_symbols(&buffer[skipframes], nr_actual_frames)
|
csymbols := C.backtrace_symbols(&buffer[skipframes], nr_actual_frames)
|
||||||
for i in 0 .. nr_actual_frames {
|
for i in 0 .. nr_actual_frames {
|
||||||
sframes << tos2( byteptr(csymbols[i]) )
|
sframes << unsafe {tos2( byteptr(csymbols[i]) )}
|
||||||
}
|
}
|
||||||
for sframe in sframes {
|
for sframe in sframes {
|
||||||
executable := sframe.all_before('(')
|
executable := sframe.all_before('(')
|
||||||
|
|
|
@ -84,10 +84,10 @@ fn (mut m SortedMap) set(key string, value voidptr) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
node = if key < parent.keys[child_index] {
|
if key < parent.keys[child_index] {
|
||||||
&mapnode(parent.children[child_index])
|
node = unsafe {&mapnode(parent.children[child_index])}
|
||||||
} else {
|
} else {
|
||||||
&mapnode(parent.children[child_index + 1])
|
node = unsafe {&mapnode(parent.children[child_index + 1])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut i := 0
|
mut i := 0
|
||||||
|
@ -116,7 +116,7 @@ fn (mut m SortedMap) set(key string, value voidptr) {
|
||||||
}
|
}
|
||||||
parent = node
|
parent = node
|
||||||
child_index = i
|
child_index = i
|
||||||
node = &mapnode(node.children[child_index])
|
node = unsafe {&mapnode(node.children[child_index])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,22 +131,30 @@ fn (mut n mapnode) split_child(child_index int, mut y mapnode) {
|
||||||
if !isnil(y.children) {
|
if !isnil(y.children) {
|
||||||
z.children = &voidptr(malloc(int(children_bytes)))
|
z.children = &voidptr(malloc(int(children_bytes)))
|
||||||
for jj := degree - 1; jj >= 0; jj-- {
|
for jj := degree - 1; jj >= 0; jj-- {
|
||||||
z.children[jj] = y.children[jj + degree]
|
unsafe {
|
||||||
|
z.children[jj] = y.children[jj + degree]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isnil(n.children) {
|
if isnil(n.children) {
|
||||||
n.children = &voidptr(malloc(int(children_bytes)))
|
n.children = &voidptr(malloc(int(children_bytes)))
|
||||||
}
|
}
|
||||||
n.children[n.len + 1] = n.children[n.len]
|
unsafe {
|
||||||
|
n.children[n.len + 1] = n.children[n.len]
|
||||||
|
}
|
||||||
for j := n.len; j > child_index; j-- {
|
for j := n.len; j > child_index; j-- {
|
||||||
n.keys[j] = n.keys[j - 1]
|
n.keys[j] = n.keys[j - 1]
|
||||||
n.values[j] = n.values[j - 1]
|
n.values[j] = n.values[j - 1]
|
||||||
n.children[j] = n.children[j - 1]
|
unsafe {
|
||||||
|
n.children[j] = n.children[j - 1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n.keys[child_index] = y.keys[mid_index]
|
n.keys[child_index] = y.keys[mid_index]
|
||||||
n.values[child_index] = y.values[mid_index]
|
n.values[child_index] = y.values[mid_index]
|
||||||
n.children[child_index] = voidptr(y)
|
unsafe {
|
||||||
n.children[child_index + 1] = voidptr(z)
|
n.children[child_index] = voidptr(y)
|
||||||
|
n.children[child_index + 1] = voidptr(z)
|
||||||
|
}
|
||||||
n.len++
|
n.len++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +172,7 @@ fn (m SortedMap) get(key string, out voidptr) bool {
|
||||||
if isnil(node.children) {
|
if isnil(node.children) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
node = &mapnode(node.children[i + 1])
|
node = unsafe {&mapnode(node.children[i + 1])}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -183,7 +191,7 @@ fn (m SortedMap) exists(key string) bool {
|
||||||
if isnil(node.children) {
|
if isnil(node.children) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
node = &mapnode(node.children[i + 1])
|
node = unsafe {&mapnode(node.children[i + 1])}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -210,15 +218,17 @@ fn (mut n mapnode) remove_key(k string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
flag := if idx == n.len {true} else {false}
|
flag := if idx == n.len {true} else {false}
|
||||||
if (&mapnode(n.children[idx])).len < degree {
|
if unsafe {&mapnode(n.children[idx])}.len < degree {
|
||||||
n.fill(idx)
|
n.fill(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut node := &mapnode(0)
|
||||||
if flag && idx > n.len {
|
if flag && idx > n.len {
|
||||||
return (&mapnode(n.children[idx - 1])).remove_key(k)
|
node = unsafe {&mapnode(n.children[idx - 1])}
|
||||||
} else {
|
} else {
|
||||||
return (&mapnode(n.children[idx])).remove_key(k)
|
node = unsafe {&mapnode(n.children[idx])}
|
||||||
}
|
}
|
||||||
|
return node.remove_key(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,34 +242,37 @@ fn (mut n mapnode) remove_from_leaf(idx int) {
|
||||||
|
|
||||||
fn (mut n mapnode) remove_from_non_leaf(idx int) {
|
fn (mut n mapnode) remove_from_non_leaf(idx int) {
|
||||||
k := n.keys[idx]
|
k := n.keys[idx]
|
||||||
if &mapnode(n.children[idx]).len >= degree {
|
if unsafe {&mapnode(n.children[idx])}.len >= degree {
|
||||||
mut current := &mapnode(n.children[idx])
|
mut current := unsafe {&mapnode(n.children[idx])}
|
||||||
for !isnil(current.children) {
|
for !isnil(current.children) {
|
||||||
current = &mapnode(current.children[current.len])
|
current = unsafe {&mapnode(current.children[current.len])}
|
||||||
}
|
}
|
||||||
predecessor := current.keys[current.len - 1]
|
predecessor := current.keys[current.len - 1]
|
||||||
n.keys[idx] = predecessor
|
n.keys[idx] = predecessor
|
||||||
n.values[idx] = current.values[current.len - 1]
|
n.values[idx] = current.values[current.len - 1]
|
||||||
(&mapnode(n.children[idx])).remove_key(predecessor)
|
node := unsafe {&mapnode(n.children[idx])}
|
||||||
} else if &mapnode(n.children[idx + 1]).len >= degree {
|
node.remove_key(predecessor)
|
||||||
mut current := &mapnode(n.children[idx + 1])
|
} else if unsafe {&mapnode(n.children[idx + 1])}.len >= degree {
|
||||||
|
mut current := unsafe {&mapnode(n.children[idx + 1])}
|
||||||
for !isnil(current.children) {
|
for !isnil(current.children) {
|
||||||
current = &mapnode(current.children[0])
|
current = unsafe {&mapnode(current.children[0])}
|
||||||
}
|
}
|
||||||
successor := current.keys[0]
|
successor := current.keys[0]
|
||||||
n.keys[idx] = successor
|
n.keys[idx] = successor
|
||||||
n.values[idx] = current.values[0]
|
n.values[idx] = current.values[0]
|
||||||
(&mapnode(n.children[idx + 1])).remove_key(successor)
|
node := unsafe {&mapnode(n.children[idx + 1])}
|
||||||
|
node.remove_key(successor)
|
||||||
} else {
|
} else {
|
||||||
n.merge(idx)
|
n.merge(idx)
|
||||||
(&mapnode(n.children[idx])).remove_key(k)
|
node := unsafe {&mapnode(n.children[idx])}
|
||||||
|
node.remove_key(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut n mapnode) fill(idx int) {
|
fn (mut n mapnode) fill(idx int) {
|
||||||
if idx != 0 && &mapnode(n.children[idx - 1]).len >= degree {
|
if idx != 0 && unsafe {&mapnode(n.children[idx - 1])}.len >= degree {
|
||||||
n.borrow_from_prev(idx)
|
n.borrow_from_prev(idx)
|
||||||
} else if idx != n.len && &mapnode(n.children[idx + 1]).len >= degree {
|
} else if idx != n.len && unsafe {&mapnode(n.children[idx + 1])}.len >= degree {
|
||||||
n.borrow_from_next(idx)
|
n.borrow_from_next(idx)
|
||||||
} else if idx != n.len {
|
} else if idx != n.len {
|
||||||
n.merge(idx)
|
n.merge(idx)
|
||||||
|
@ -269,21 +282,25 @@ fn (mut n mapnode) fill(idx int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut n mapnode) borrow_from_prev(idx int) {
|
fn (mut n mapnode) borrow_from_prev(idx int) {
|
||||||
mut child := &mapnode(n.children[idx])
|
mut child := unsafe {&mapnode(n.children[idx])}
|
||||||
mut sibling := &mapnode(n.children[idx - 1])
|
mut sibling := unsafe {&mapnode(n.children[idx - 1])}
|
||||||
for i := child.len - 1; i >= 0; i-- {
|
for i := child.len - 1; i >= 0; i-- {
|
||||||
child.keys[i + 1] = child.keys[i]
|
child.keys[i + 1] = child.keys[i]
|
||||||
child.values[i + 1] = child.values[i]
|
child.values[i + 1] = child.values[i]
|
||||||
}
|
}
|
||||||
if !isnil(child.children) {
|
if !isnil(child.children) {
|
||||||
for i := child.len; i >= 0; i-- {
|
for i := child.len; i >= 0; i-- {
|
||||||
child.children[i + 1] = child.children[i]
|
unsafe {
|
||||||
|
child.children[i + 1] = child.children[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
child.keys[0] = n.keys[idx - 1]
|
child.keys[0] = n.keys[idx - 1]
|
||||||
child.values[0] = n.values[idx - 1]
|
child.values[0] = n.values[idx - 1]
|
||||||
if !isnil(child.children) {
|
if !isnil(child.children) {
|
||||||
child.children[0] = sibling.children[sibling.len]
|
unsafe {
|
||||||
|
child.children[0] = sibling.children[sibling.len]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n.keys[idx - 1] = sibling.keys[sibling.len - 1]
|
n.keys[idx - 1] = sibling.keys[sibling.len - 1]
|
||||||
n.values[idx - 1] = sibling.values[sibling.len - 1]
|
n.values[idx - 1] = sibling.values[sibling.len - 1]
|
||||||
|
@ -292,12 +309,14 @@ fn (mut n mapnode) borrow_from_prev(idx int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut n mapnode) borrow_from_next(idx int) {
|
fn (mut n mapnode) borrow_from_next(idx int) {
|
||||||
mut child := &mapnode(n.children[idx])
|
mut child := unsafe {&mapnode(n.children[idx])}
|
||||||
mut sibling := &mapnode(n.children[idx + 1])
|
mut sibling := unsafe {&mapnode(n.children[idx + 1])}
|
||||||
child.keys[child.len] = n.keys[idx]
|
child.keys[child.len] = n.keys[idx]
|
||||||
child.values[child.len] = n.values[idx]
|
child.values[child.len] = n.values[idx]
|
||||||
if !isnil(child.children) {
|
if !isnil(child.children) {
|
||||||
child.children[child.len + 1] = sibling.children[0]
|
unsafe {
|
||||||
|
child.children[child.len + 1] = sibling.children[0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n.keys[idx] = sibling.keys[0]
|
n.keys[idx] = sibling.keys[0]
|
||||||
n.values[idx] = sibling.values[0]
|
n.values[idx] = sibling.values[0]
|
||||||
|
@ -307,7 +326,9 @@ fn (mut n mapnode) borrow_from_next(idx int) {
|
||||||
}
|
}
|
||||||
if !isnil(sibling.children) {
|
if !isnil(sibling.children) {
|
||||||
for i := 1; i <= sibling.len; i++ {
|
for i := 1; i <= sibling.len; i++ {
|
||||||
sibling.children[i - 1] = sibling.children[i]
|
unsafe {
|
||||||
|
sibling.children[i - 1] = sibling.children[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
child.len++
|
child.len++
|
||||||
|
@ -315,8 +336,8 @@ fn (mut n mapnode) borrow_from_next(idx int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut n mapnode) merge(idx int) {
|
fn (mut n mapnode) merge(idx int) {
|
||||||
mut child := &mapnode(n.children[idx])
|
mut child := unsafe {&mapnode(n.children[idx])}
|
||||||
sibling := &mapnode(n.children[idx + 1])
|
sibling := unsafe {&mapnode(n.children[idx + 1])}
|
||||||
child.keys[mid_index] = n.keys[idx]
|
child.keys[mid_index] = n.keys[idx]
|
||||||
child.values[mid_index] = n.values[idx]
|
child.values[mid_index] = n.values[idx]
|
||||||
for i in 0..sibling.len {
|
for i in 0..sibling.len {
|
||||||
|
@ -325,7 +346,9 @@ fn (mut n mapnode) merge(idx int) {
|
||||||
}
|
}
|
||||||
if !isnil(child.children) {
|
if !isnil(child.children) {
|
||||||
for i := 0; i <= sibling.len; i++ {
|
for i := 0; i <= sibling.len; i++ {
|
||||||
child.children[i + degree] = sibling.children[i]
|
unsafe {
|
||||||
|
child.children[i + degree] = sibling.children[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := idx + 1; i < n.len; i++ {
|
for i := idx + 1; i < n.len; i++ {
|
||||||
|
@ -333,7 +356,9 @@ fn (mut n mapnode) merge(idx int) {
|
||||||
n.values[i - 1] = n.values[i]
|
n.values[i - 1] = n.values[i]
|
||||||
}
|
}
|
||||||
for i := idx + 2; i <= n.len; i++ {
|
for i := idx + 2; i <= n.len; i++ {
|
||||||
n.children[i - 1] = n.children[i]
|
unsafe {
|
||||||
|
n.children[i - 1] = n.children[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
child.len += sibling.len + 1
|
child.len += sibling.len + 1
|
||||||
n.len--
|
n.len--
|
||||||
|
@ -355,7 +380,7 @@ pub fn (mut m SortedMap) delete(key string) {
|
||||||
if isnil(m.root.children) {
|
if isnil(m.root.children) {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
m.root = &mapnode(m.root.children[0])
|
m.root = unsafe {&mapnode(m.root.children[0])}
|
||||||
}
|
}
|
||||||
// free(tmp)
|
// free(tmp)
|
||||||
}
|
}
|
||||||
|
@ -369,13 +394,13 @@ fn (n &mapnode) subkeys(mut keys []string, at int) int {
|
||||||
// Traverse children and insert
|
// Traverse children and insert
|
||||||
// keys inbetween children
|
// keys inbetween children
|
||||||
for i in 0..n.len {
|
for i in 0..n.len {
|
||||||
child := &mapnode(n.children[i])
|
child := unsafe {&mapnode(n.children[i])}
|
||||||
position += child.subkeys(mut keys, position)
|
position += child.subkeys(mut keys, position)
|
||||||
keys[position] = n.keys[i]
|
keys[position] = n.keys[i]
|
||||||
position++
|
position++
|
||||||
}
|
}
|
||||||
// Insert the keys of the last child
|
// Insert the keys of the last child
|
||||||
child := &mapnode(n.children[n.len])
|
child := unsafe {&mapnode(n.children[n.len])}
|
||||||
position += child.subkeys(mut keys, position)
|
position += child.subkeys(mut keys, position)
|
||||||
} else {
|
} else {
|
||||||
// If leaf, insert keys
|
// If leaf, insert keys
|
||||||
|
|
|
@ -147,6 +147,7 @@ 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
|
||||||
|
[unsafe_fn]
|
||||||
pub fn cstring_to_vstring(cstr byteptr) string {
|
pub fn cstring_to_vstring(cstr byteptr) string {
|
||||||
return tos_clone(cstr)
|
return tos_clone(cstr)
|
||||||
}
|
}
|
||||||
|
@ -1432,12 +1433,16 @@ pub fn (s string) filter(func fn(b byte) bool) string {
|
||||||
for i in 0 .. s.len {
|
for i in 0 .. s.len {
|
||||||
mut b := s[i]
|
mut b := s[i]
|
||||||
if func(b) {
|
if func(b) {
|
||||||
buf[new_len] = b
|
unsafe {
|
||||||
|
buf[new_len] = b
|
||||||
|
}
|
||||||
new_len++
|
new_len++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf[new_len] = 0
|
unsafe {
|
||||||
return string(buf, new_len)
|
buf[new_len] = 0
|
||||||
|
return string(buf, new_len)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows multi-line strings to be formatted in a way that removes white-space
|
// Allows multi-line strings to be formatted in a way that removes white-space
|
||||||
|
|
|
@ -10,76 +10,45 @@ pub fn utf8_char_len(b byte) int {
|
||||||
// Convert utf32 to utf8
|
// Convert utf32 to utf8
|
||||||
// utf32 == Codepoint
|
// utf32 == Codepoint
|
||||||
pub fn utf32_to_str(code u32) string {
|
pub fn utf32_to_str(code u32) string {
|
||||||
icode := int(code) // Prevents doing casts everywhere
|
|
||||||
mut buffer := malloc(5)
|
mut buffer := malloc(5)
|
||||||
if icode <= 127/* 0x7F */ {
|
return utf32_to_str_no_malloc(code, buffer)
|
||||||
buffer[0] = byte(icode)
|
|
||||||
return tos(buffer, 1)
|
|
||||||
}
|
|
||||||
if icode <= 2047/* 0x7FF */ {
|
|
||||||
buffer[0] = 192/*0xC0*/ | byte(icode>>6)/* 110xxxxx */
|
|
||||||
|
|
||||||
buffer[1] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
|
||||||
|
|
||||||
return tos(buffer, 2)
|
|
||||||
}
|
|
||||||
if icode <= 65535/* 0xFFFF */ {
|
|
||||||
buffer[0] = 224/*0xE0*/ | byte(icode>>12)/* 1110xxxx */
|
|
||||||
|
|
||||||
buffer[1] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
|
|
||||||
|
|
||||||
buffer[2] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
|
||||||
|
|
||||||
return tos(buffer, 3)
|
|
||||||
}
|
|
||||||
if icode <= 1114111/* 0x10FFFF */ {
|
|
||||||
buffer[0] = 240/*0xF0*/ | byte(icode>>18)/* 11110xxx */
|
|
||||||
|
|
||||||
buffer[1] = 128/*0x80*/ | (byte(icode>>12) & 63/*0x3F*/)/* 10xxxxxx */
|
|
||||||
|
|
||||||
buffer[2] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
|
|
||||||
|
|
||||||
buffer[3] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
|
||||||
|
|
||||||
return tos(buffer, 4)
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO copypasta
|
|
||||||
pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string {
|
pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string {
|
||||||
icode := int(code) // Prevents doing casts everywhere
|
icode := int(code) // Prevents doing casts everywhere
|
||||||
mut buffer := byteptr(buf)
|
unsafe {
|
||||||
if icode <= 127/* 0x7F */ {
|
mut buffer := byteptr(buf)
|
||||||
buffer[0] = byte(icode)
|
if icode <= 127/* 0x7F */ {
|
||||||
return tos(buffer, 1)
|
buffer[0] = byte(icode)
|
||||||
}
|
return tos(buffer, 1)
|
||||||
if icode <= 2047/* 0x7FF */ {
|
}
|
||||||
buffer[0] = 192/*0xC0*/ | byte(icode>>6)/* 110xxxxx */
|
if icode <= 2047/* 0x7FF */ {
|
||||||
|
buffer[0] = 192/*0xC0*/ | byte(icode>>6)/* 110xxxxx */
|
||||||
|
|
||||||
buffer[1] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
buffer[1] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
||||||
|
|
||||||
return tos(buffer, 2)
|
return tos(buffer, 2)
|
||||||
}
|
}
|
||||||
if icode <= 65535/* 0xFFFF */ {
|
if icode <= 65535/* 0xFFFF */ {
|
||||||
buffer[0] = 224/*0xE0*/ | byte(icode>>12)/* 1110xxxx */
|
buffer[0] = 224/*0xE0*/ | byte(icode>>12)/* 1110xxxx */
|
||||||
|
|
||||||
buffer[1] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
|
buffer[1] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
|
||||||
|
|
||||||
buffer[2] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
buffer[2] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
||||||
|
|
||||||
return tos(buffer, 3)
|
return tos(buffer, 3)
|
||||||
}
|
}
|
||||||
if icode <= 1114111/* 0x10FFFF */ {
|
if icode <= 1114111/* 0x10FFFF */ {
|
||||||
buffer[0] = 240/*0xF0*/ | byte(icode>>18)/* 11110xxx */
|
buffer[0] = 240/*0xF0*/ | byte(icode>>18)/* 11110xxx */
|
||||||
|
|
||||||
buffer[1] = 128/*0x80*/ | (byte(icode>>12) & 63/*0x3F*/)/* 10xxxxxx */
|
buffer[1] = 128/*0x80*/ | (byte(icode>>12) & 63/*0x3F*/)/* 10xxxxxx */
|
||||||
|
|
||||||
buffer[2] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
|
buffer[2] = 128/*0x80*/ | (byte(icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
|
||||||
|
|
||||||
buffer[3] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
buffer[3] = 128/*0x80*/ | byte(icode & 63/*0x3F*/)/* 10xxxxxx */
|
||||||
|
|
||||||
return tos(buffer, 4)
|
return tos(buffer, 4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -183,7 +152,7 @@ fn utf8_str_len(s string) int {
|
||||||
mut l := 0
|
mut l := 0
|
||||||
for i := 0; i < s.len; i++ {
|
for i := 0; i < s.len; i++ {
|
||||||
l++
|
l++
|
||||||
c := s.str[i]
|
c := unsafe {s.str[i]}
|
||||||
if (c & (1 << 7)) != 0 {
|
if (c & (1 << 7)) != 0 {
|
||||||
for t := byte(1 << 6); (c & t) != 0; t >>= 1 {
|
for t := byte(1 << 6); (c & t) != 0; t >>= 1 {
|
||||||
i++
|
i++
|
||||||
|
@ -199,7 +168,7 @@ fn utf8_str_visible_length(s string) int {
|
||||||
mut ul := 1
|
mut ul := 1
|
||||||
for i := 0; i < s.len; i+=ul {
|
for i := 0; i < s.len; i+=ul {
|
||||||
ul = 1
|
ul = 1
|
||||||
c := s.str[i]
|
c := unsafe {s.str[i]}
|
||||||
if (c & (1 << 7)) != 0 {
|
if (c & (1 << 7)) != 0 {
|
||||||
for t := byte(1 << 6); (c & t) != 0; t >>= 1 {
|
for t := byte(1 << 6); (c & t) != 0; t >>= 1 {
|
||||||
ul++
|
ul++
|
||||||
|
@ -211,12 +180,12 @@ fn utf8_str_visible_length(s string) int {
|
||||||
l++
|
l++
|
||||||
// recognize combining characters
|
// recognize combining characters
|
||||||
if c == 0xcc || c == 0xcd {
|
if c == 0xcc || c == 0xcd {
|
||||||
r := (u16(c) << 8) | s.str[i+1]
|
r := (u16(c) << 8) | unsafe {s.str[i+1]}
|
||||||
if r >= 0xcc80 && r < 0xcdb0 { // diacritical marks
|
if r >= 0xcc80 && r < 0xcdb0 { // diacritical marks
|
||||||
l--
|
l--
|
||||||
}
|
}
|
||||||
} else if c == 0xe1 || c == 0xe2 || c == 0xef {
|
} else if c == 0xe1 || c == 0xe2 || c == 0xef {
|
||||||
r := (u32(c) << 16) | (u32(s.str[i+1]) << 8) | s.str[i+2]
|
r := (u32(c) << 16) | unsafe {(u32(s.str[i+1]) << 8) | s.str[i+2]}
|
||||||
if (r >= 0xe1aab0 && r < 0xe1ac80) // diacritical marks extended
|
if (r >= 0xe1aab0 && r < 0xe1ac80) // diacritical marks extended
|
||||||
|| (r >= 0xe1b780 && r < 0xe1b880) // diacritical marks supplement
|
|| (r >= 0xe1b780 && r < 0xe1b880) // diacritical marks supplement
|
||||||
|| (r >= 0xe28390 && r < 0xe28480) // diacritical marks for symbols
|
|| (r >= 0xe28390 && r < 0xe28480) // diacritical marks for symbols
|
||||||
|
|
|
@ -84,26 +84,28 @@ pub fn decode_in_buffer(data &string, buffer byteptr) int {
|
||||||
mut char_c := 0
|
mut char_c := 0
|
||||||
mut char_d := 0
|
mut char_d := 0
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_a = index[d[i]]
|
char_a = index[unsafe {d[i]}]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_b = index[d[i]]
|
char_b = index[unsafe {d[i]}]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_c = index[d[i]]
|
char_c = index[unsafe {d[i]}]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_d = index[d[i]]
|
char_d = index[unsafe {d[i]}]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded_bytes := (char_a << 18) | (char_b << 12) | (char_c << 6) | (char_d << 0)
|
decoded_bytes := (char_a << 18) | (char_b << 12) | (char_c << 6) | (char_d << 0)
|
||||||
b[j] = byte(decoded_bytes >> 16)
|
unsafe {
|
||||||
b[j+1] = byte((decoded_bytes >> 8) & 0xff)
|
b[j] = byte(decoded_bytes >> 16)
|
||||||
b[j+2] = byte((decoded_bytes >> 0) & 0xff)
|
b[j+1] = byte((decoded_bytes >> 8) & 0xff)
|
||||||
|
b[j+2] = byte((decoded_bytes >> 0) & 0xff)
|
||||||
|
}
|
||||||
j += 3
|
j += 3
|
||||||
}
|
}
|
||||||
return output_length
|
return output_length
|
||||||
|
@ -139,30 +141,34 @@ pub fn encode_in_buffer(data &string, buffer byteptr) int {
|
||||||
mut octet_c := 0
|
mut octet_c := 0
|
||||||
|
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
octet_a = int(d[i])
|
octet_a = int(unsafe {d[i]})
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
octet_b = int(d[i])
|
octet_b = int(unsafe {d[i]})
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
octet_c = int(d[i])
|
octet_c = int(unsafe {d[i]})
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
triple := ((octet_a << 0x10) + (octet_b << 0x08) + octet_c)
|
triple := ((octet_a << 0x10) + (octet_b << 0x08) + octet_c)
|
||||||
|
|
||||||
b[j] = etable[ (triple >> 3 * 6) & 63 ] // 63 is 0x3F
|
unsafe {
|
||||||
b[j+1] = etable[ (triple >> 2 * 6) & 63 ]
|
b[j] = etable[ (triple >> 3 * 6) & 63 ] // 63 is 0x3F
|
||||||
b[j+2] = etable[ (triple >> 1 * 6) & 63 ]
|
b[j+1] = etable[ (triple >> 2 * 6) & 63 ]
|
||||||
b[j+3] = etable[ (triple >> 0 * 6) & 63 ]
|
b[j+2] = etable[ (triple >> 1 * 6) & 63 ]
|
||||||
|
b[j+3] = etable[ (triple >> 0 * 6) & 63 ]
|
||||||
|
}
|
||||||
j += 4
|
j += 4
|
||||||
}
|
}
|
||||||
|
|
||||||
padding_length := ending_table[input_length % 3]
|
padding_length := ending_table[input_length % 3]
|
||||||
for i = 0; i < padding_length; i++ {
|
for i = 0; i < padding_length; i++ {
|
||||||
b[output_length - 1 - i] = `=`
|
unsafe {
|
||||||
|
b[output_length - 1 - i] = `=`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output_length
|
return output_length
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub fn validate_str(str string) bool {
|
||||||
pub fn validate(data byteptr, len int) bool {
|
pub fn validate(data byteptr, len int) bool {
|
||||||
mut state := Utf8State{}
|
mut state := Utf8State{}
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
s := data[i]
|
s := unsafe {data[i]}
|
||||||
if s == 0 {
|
if s == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,16 @@ fn (mut ws Client) read_handshake(seckey string) {
|
||||||
if res == 0 || res == -1 {
|
if res == 0 || res == -1 {
|
||||||
ws.log.fatal('read_handshake: Failed to read handshake.')
|
ws.log.fatal('read_handshake: Failed to read handshake.')
|
||||||
}
|
}
|
||||||
if buffer[bytes_read] == `\n` &&
|
if unsafe {buffer[bytes_read] == `\n` &&
|
||||||
buffer[bytes_read - 1] == `\r` && buffer[bytes_read - 2] == `\n` &&
|
buffer[bytes_read - 1] == `\r` && buffer[bytes_read - 2] == `\n` &&
|
||||||
buffer[bytes_read - 3] == `\r` {
|
buffer[bytes_read - 3] == `\r`} {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bytes_read += buffer_size
|
bytes_read += buffer_size
|
||||||
}
|
}
|
||||||
buffer[max_buffer - 1] = `\0`
|
unsafe {
|
||||||
|
buffer[max_buffer - 1] = `\0`
|
||||||
|
}
|
||||||
ws.handshake_handler(string(byteptr(buffer)), seckey)
|
ws.handshake_handler(string(byteptr(buffer)), seckey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,18 @@ import crypto.sha1
|
||||||
import encoding.base64
|
import encoding.base64
|
||||||
|
|
||||||
fn htonl64(payload_len u64) byteptr {
|
fn htonl64(payload_len u64) byteptr {
|
||||||
mut ret := malloc(8)
|
unsafe {
|
||||||
ret[0] = byte(((payload_len & (u64(0xff) << 56)) >> 56) & 0xff)
|
mut ret := malloc(8)
|
||||||
ret[1] = byte(((payload_len & (u64(0xff) << 48)) >> 48) & 0xff)
|
ret[0] = byte(((payload_len & (u64(0xff) << 56)) >> 56) & 0xff)
|
||||||
ret[2] = byte(((payload_len & (u64(0xff) << 40)) >> 40) & 0xff)
|
ret[1] = byte(((payload_len & (u64(0xff) << 48)) >> 48) & 0xff)
|
||||||
ret[3] = byte(((payload_len & (u64(0xff) << 32)) >> 32) & 0xff)
|
ret[2] = byte(((payload_len & (u64(0xff) << 40)) >> 40) & 0xff)
|
||||||
ret[4] = byte(((payload_len & (u64(0xff) << 24)) >> 24) & 0xff)
|
ret[3] = byte(((payload_len & (u64(0xff) << 32)) >> 32) & 0xff)
|
||||||
ret[5] = byte(((payload_len & (u64(0xff) << 16)) >> 16) & 0xff)
|
ret[4] = byte(((payload_len & (u64(0xff) << 24)) >> 24) & 0xff)
|
||||||
ret[6] = byte(((payload_len & (u64(0xff) << 8)) >> 8) & 0xff)
|
ret[5] = byte(((payload_len & (u64(0xff) << 16)) >> 16) & 0xff)
|
||||||
ret[7] = byte(((payload_len & (u64(0xff) << 0)) >> 0) & 0xff)
|
ret[6] = byte(((payload_len & (u64(0xff) << 8)) >> 8) & 0xff)
|
||||||
return ret
|
ret[7] = byte(((payload_len & (u64(0xff) << 0)) >> 0) & 0xff)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_masking_key() []byte {
|
fn create_masking_key() []byte {
|
||||||
|
|
|
@ -355,19 +355,20 @@ pub fn (mut ws Client) read() int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bytes_read == u64(header_len_offset) {
|
if bytes_read == u64(header_len_offset) {
|
||||||
frame.fin = (data[0] & 0x80) == 0x80
|
data0 := unsafe {data[0]}
|
||||||
frame.rsv1 = (data[0] & 0x40) == 0x40
|
frame.fin = (data0 & 0x80) == 0x80
|
||||||
frame.rsv2 = (data[0] & 0x20) == 0x20
|
frame.rsv1 = (data0 & 0x40) == 0x40
|
||||||
frame.rsv3 = (data[0] & 0x10) == 0x10
|
frame.rsv2 = (data0 & 0x20) == 0x20
|
||||||
frame.opcode = OPCode(int(data[0] & 0x7F))
|
frame.rsv3 = (data0 & 0x10) == 0x10
|
||||||
frame.mask = (data[1] & 0x80) == 0x80
|
frame.opcode = OPCode(int(data0 & 0x7F))
|
||||||
frame.payload_len = u64(data[1] & 0x7F)
|
frame.mask = (unsafe {data[1]} & 0x80) == 0x80
|
||||||
|
frame.payload_len = u64(unsafe {data[1]} & 0x7F)
|
||||||
// masking key
|
// masking key
|
||||||
if frame.mask {
|
if frame.mask {
|
||||||
frame.masking_key[0] = data[2]
|
frame.masking_key[0] = unsafe {data[2]}
|
||||||
frame.masking_key[1] = data[3]
|
frame.masking_key[1] = unsafe {data[3]}
|
||||||
frame.masking_key[2] = data[4]
|
frame.masking_key[2] = unsafe {data[4]}
|
||||||
frame.masking_key[3] = data[5]
|
frame.masking_key[3] = unsafe {data[5]}
|
||||||
}
|
}
|
||||||
payload_len = frame.payload_len
|
payload_len = frame.payload_len
|
||||||
frame_size = u64(header_len) + payload_len
|
frame_size = u64(header_len) + payload_len
|
||||||
|
@ -375,14 +376,14 @@ pub fn (mut ws Client) read() int {
|
||||||
if frame.payload_len == u64(126) && bytes_read == u64(extended_payload16_end_byte) {
|
if frame.payload_len == u64(126) && bytes_read == u64(extended_payload16_end_byte) {
|
||||||
header_len += 2
|
header_len += 2
|
||||||
mut extended_payload_len := 0
|
mut extended_payload_len := 0
|
||||||
extended_payload_len |= data[2] << 8
|
extended_payload_len |= unsafe {data[2]} << 8
|
||||||
extended_payload_len |= data[3] << 0
|
extended_payload_len |= unsafe {data[3]} << 0
|
||||||
// masking key
|
// masking key
|
||||||
if frame.mask {
|
if frame.mask {
|
||||||
frame.masking_key[0] = data[4]
|
frame.masking_key[0] = unsafe {data[4]}
|
||||||
frame.masking_key[1] = data[5]
|
frame.masking_key[1] = unsafe {data[5]}
|
||||||
frame.masking_key[2] = data[6]
|
frame.masking_key[2] = unsafe {data[6]}
|
||||||
frame.masking_key[3] = data[7]
|
frame.masking_key[3] = unsafe {data[7]}
|
||||||
}
|
}
|
||||||
payload_len = u64(extended_payload_len)
|
payload_len = u64(extended_payload_len)
|
||||||
frame_size = u64(header_len) + payload_len
|
frame_size = u64(header_len) + payload_len
|
||||||
|
@ -393,20 +394,20 @@ pub fn (mut ws Client) read() int {
|
||||||
} else if frame.payload_len == u64(127) && bytes_read == u64(extended_payload64_end_byte) {
|
} else if frame.payload_len == u64(127) && bytes_read == u64(extended_payload64_end_byte) {
|
||||||
header_len += 8 // TODO Not sure...
|
header_len += 8 // TODO Not sure...
|
||||||
mut extended_payload_len := u64(0)
|
mut extended_payload_len := u64(0)
|
||||||
extended_payload_len |= u64(data[2]) << 56
|
extended_payload_len |= u64(unsafe {data[2]}) << 56
|
||||||
extended_payload_len |= u64(data[3]) << 48
|
extended_payload_len |= u64(unsafe {data[3]}) << 48
|
||||||
extended_payload_len |= u64(data[4]) << 40
|
extended_payload_len |= u64(unsafe {data[4]}) << 40
|
||||||
extended_payload_len |= u64(data[5]) << 32
|
extended_payload_len |= u64(unsafe {data[5]}) << 32
|
||||||
extended_payload_len |= u64(data[6]) << 24
|
extended_payload_len |= u64(unsafe {data[6]}) << 24
|
||||||
extended_payload_len |= u64(data[7]) << 16
|
extended_payload_len |= u64(unsafe {data[7]}) << 16
|
||||||
extended_payload_len |= u64(data[8]) << 8
|
extended_payload_len |= u64(unsafe {data[8]}) << 8
|
||||||
extended_payload_len |= u64(data[9]) << 0
|
extended_payload_len |= u64(unsafe {data[9]}) << 0
|
||||||
// masking key
|
// masking key
|
||||||
if frame.mask {
|
if frame.mask {
|
||||||
frame.masking_key[0] = data[10]
|
frame.masking_key[0] = unsafe {data[10]}
|
||||||
frame.masking_key[1] = data[11]
|
frame.masking_key[1] = unsafe {data[11]}
|
||||||
frame.masking_key[2] = data[12]
|
frame.masking_key[2] = unsafe {data[12]}
|
||||||
frame.masking_key[3] = data[13]
|
frame.masking_key[3] = unsafe {data[13]}
|
||||||
}
|
}
|
||||||
payload_len = extended_payload_len
|
payload_len = extended_payload_len
|
||||||
frame_size = u64(header_len) + payload_len
|
frame_size = u64(header_len) + payload_len
|
||||||
|
@ -419,7 +420,9 @@ pub fn (mut ws Client) read() int {
|
||||||
// unmask the payload
|
// unmask the payload
|
||||||
if frame.mask {
|
if frame.mask {
|
||||||
for i in 0 .. payload_len {
|
for i in 0 .. payload_len {
|
||||||
data[header_len + i] ^= frame.masking_key[i % 4] & 0xff
|
unsafe {
|
||||||
|
data[header_len + i] ^= frame.masking_key[i % 4] & 0xff
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ws.fragments.len > 0 && frame.opcode in [.text_frame, .binary_frame] {
|
if ws.fragments.len > 0 && frame.opcode in [.text_frame, .binary_frame] {
|
||||||
|
@ -474,11 +477,13 @@ pub fn (mut ws Client) read() int {
|
||||||
}
|
}
|
||||||
ws.fragments = []
|
ws.fragments = []
|
||||||
}
|
}
|
||||||
payload[payload_len] = `\0`
|
unsafe {
|
||||||
|
payload[payload_len] = `\0`
|
||||||
|
}
|
||||||
if frame.opcode == .text_frame && payload_len > 0 {
|
if frame.opcode == .text_frame && payload_len > 0 {
|
||||||
if !utf8.validate(payload, int(payload_len)) {
|
if !utf8.validate(payload, int(payload_len)) {
|
||||||
ws.log.error('malformed utf8 payload')
|
ws.log.error('malformed utf8 payload')
|
||||||
ws.send_error_event('Recieved malformed utf8.')
|
ws.send_error_event('Received malformed utf8.')
|
||||||
ws.close(1007, 'malformed utf8 payload')
|
ws.close(1007, 'malformed utf8 payload')
|
||||||
goto free_data
|
goto free_data
|
||||||
return -1
|
return -1
|
||||||
|
@ -556,10 +561,10 @@ pub fn (mut ws Client) read() int {
|
||||||
mut code := 0
|
mut code := 0
|
||||||
mut reason := ''
|
mut reason := ''
|
||||||
if payload_len > 2 {
|
if payload_len > 2 {
|
||||||
code = (int(data[header_len]) << 8) + int(data[header_len + 1])
|
code = (int(unsafe {data[header_len]}) << 8) + int(unsafe {data[header_len + 1]})
|
||||||
header_len += 2
|
header_len += 2
|
||||||
payload_len -= 2
|
payload_len -= 2
|
||||||
reason = string(&data[header_len])
|
reason = unsafe {string(&data[header_len])}
|
||||||
ws.log.info('Closing with reason: $reason & code: $code')
|
ws.log.info('Closing with reason: $reason & code: $code')
|
||||||
if reason.len > 1 && !utf8.validate(reason.str, reason.len) {
|
if reason.len > 1 && !utf8.validate(reason.str, reason.len) {
|
||||||
ws.log.error('malformed utf8 payload')
|
ws.log.error('malformed utf8 payload')
|
||||||
|
|
|
@ -76,8 +76,8 @@ pub fn environ() map[string]string {
|
||||||
C.FreeEnvironmentStringsW(estrings)
|
C.FreeEnvironmentStringsW(estrings)
|
||||||
} $else {
|
} $else {
|
||||||
e := &charptr(C.environ)
|
e := &charptr(C.environ)
|
||||||
for i := 0; !isnil(e[i]); i++ {
|
for i := 0; !isnil(unsafe {e[i]}); i++ {
|
||||||
eline := cstring_to_vstring(byteptr(e[i]))
|
eline := unsafe {cstring_to_vstring(byteptr(e[i]))}
|
||||||
eq_index := eline.index_byte(`=`)
|
eq_index := eline.index_byte(`=`)
|
||||||
if eq_index > 0 {
|
if eq_index > 0 {
|
||||||
res[eline[0..eq_index]] = eline[eq_index + 1..]
|
res[eline[0..eq_index]] = eline[eq_index + 1..]
|
||||||
|
|
11
vlib/os/os.v
11
vlib/os/os.v
|
@ -120,11 +120,12 @@ pub fn read_file(path string) ?string {
|
||||||
fsize := C.ftell(fp)
|
fsize := C.ftell(fp)
|
||||||
// C.fseek(fp, 0, SEEK_SET) // same as `C.rewind(fp)` below
|
// C.fseek(fp, 0, SEEK_SET) // same as `C.rewind(fp)` below
|
||||||
C.rewind(fp)
|
C.rewind(fp)
|
||||||
mut str := &byte(0)
|
unsafe {
|
||||||
unsafe { str = malloc(fsize + 1) }
|
mut str := malloc(fsize + 1)
|
||||||
C.fread(str, fsize, 1, fp)
|
C.fread(str, fsize, 1, fp)
|
||||||
str[fsize] = 0
|
str[fsize] = 0
|
||||||
return string(str,fsize)
|
return string(str,fsize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************** Utility ops ************************/
|
/***************************** Utility ops ************************/
|
||||||
|
|
|
@ -52,7 +52,7 @@ fn init_os_args(argc int, argv &&byte) []string {
|
||||||
// mut args := []string{len:argc}
|
// mut args := []string{len:argc}
|
||||||
for i in 0 .. argc {
|
for i in 0 .. argc {
|
||||||
// args [i] = string(argv[i])
|
// args [i] = string(argv[i])
|
||||||
args << string(argv[i])
|
args << unsafe {string(argv[i])}
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ mut:
|
||||||
fn init_os_args_wide(argc int, argv &byteptr) []string {
|
fn init_os_args_wide(argc int, argv &byteptr) []string {
|
||||||
mut args := []string{}
|
mut args := []string{}
|
||||||
for i in 0..argc {
|
for i in 0..argc {
|
||||||
args << string_from_wide(&u16(argv[i]))
|
args << string_from_wide(unsafe {&u16(argv[i])})
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,9 @@ const (
|
||||||
pub fn string(len int) string {
|
pub fn string(len int) string {
|
||||||
mut buf := malloc(len)
|
mut buf := malloc(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
buf[i] = chars[intn(chars.len)]
|
unsafe {
|
||||||
|
buf[i] = chars[intn(chars.len)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return string(buf, len)
|
return string(buf, len)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,18 +90,19 @@ fn utf8util_char_len(b byte) int {
|
||||||
// get_char get a char from position i and return an u32 with the unicode code
|
// get_char get a char from position i and return an u32 with the unicode code
|
||||||
[inline]
|
[inline]
|
||||||
fn (re RE) get_char(in_txt string, i int) (u32,int) {
|
fn (re RE) get_char(in_txt string, i int) (u32,int) {
|
||||||
|
ini := unsafe {in_txt.str[i]}
|
||||||
// ascii 8 bit
|
// ascii 8 bit
|
||||||
if (re.flag & f_bin) !=0 ||
|
if (re.flag & f_bin) !=0 ||
|
||||||
in_txt.str[i] & 0x80 == 0
|
ini & 0x80 == 0
|
||||||
{
|
{
|
||||||
return u32(in_txt.str[i]), 1
|
return u32(ini), 1
|
||||||
}
|
}
|
||||||
// unicode char
|
// unicode char
|
||||||
char_len := utf8util_char_len(in_txt.str[i])
|
char_len := utf8util_char_len(ini)
|
||||||
mut tmp := 0
|
mut tmp := 0
|
||||||
mut ch := u32(0)
|
mut ch := u32(0)
|
||||||
for tmp < char_len {
|
for tmp < char_len {
|
||||||
ch = (ch << 8) | in_txt.str[i+tmp]
|
ch = (ch << 8) | unsafe {in_txt.str[i+tmp]}
|
||||||
tmp++
|
tmp++
|
||||||
}
|
}
|
||||||
return ch,char_len
|
return ch,char_len
|
||||||
|
@ -112,16 +113,16 @@ fn (re RE) get_char(in_txt string, i int) (u32,int) {
|
||||||
fn (re RE) get_charb(in_txt byteptr, i int) (u32,int) {
|
fn (re RE) get_charb(in_txt byteptr, i int) (u32,int) {
|
||||||
// ascii 8 bit
|
// ascii 8 bit
|
||||||
if (re.flag & f_bin) !=0 ||
|
if (re.flag & f_bin) !=0 ||
|
||||||
in_txt[i] & 0x80 == 0
|
unsafe {in_txt[i]} & 0x80 == 0
|
||||||
{
|
{
|
||||||
return u32(in_txt[i]), 1
|
return u32(unsafe {in_txt[i]}), 1
|
||||||
}
|
}
|
||||||
// unicode char
|
// unicode char
|
||||||
char_len := utf8util_char_len(in_txt[i])
|
char_len := utf8util_char_len(unsafe {in_txt[i]})
|
||||||
mut tmp := 0
|
mut tmp := 0
|
||||||
mut ch := u32(0)
|
mut ch := u32(0)
|
||||||
for tmp < char_len {
|
for tmp < char_len {
|
||||||
ch = (ch << 8) | in_txt[i+tmp]
|
ch = (ch << 8) | unsafe {in_txt[i+tmp]}
|
||||||
tmp++
|
tmp++
|
||||||
}
|
}
|
||||||
return ch,char_len
|
return ch,char_len
|
||||||
|
@ -488,15 +489,19 @@ fn (re RE) get_char_class(pc int) string {
|
||||||
for cc_i >= 0 && cc_i < re.cc.len && re.cc[cc_i].cc_type != cc_end {
|
for cc_i >= 0 && cc_i < re.cc.len && re.cc[cc_i].cc_type != cc_end {
|
||||||
|
|
||||||
if re.cc[cc_i].cc_type == cc_bsls {
|
if re.cc[cc_i].cc_type == cc_bsls {
|
||||||
buf_ptr[i++] = `\\`
|
unsafe {
|
||||||
buf_ptr[i++] = byte(re.cc[cc_i].ch0)
|
buf_ptr[i++] = `\\`
|
||||||
|
buf_ptr[i++] = byte(re.cc[cc_i].ch0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if re.cc[cc_i].ch0 == re.cc[cc_i].ch1 {
|
else if re.cc[cc_i].ch0 == re.cc[cc_i].ch1 {
|
||||||
tmp = 3
|
tmp = 3
|
||||||
for tmp >= 0 {
|
for tmp >= 0 {
|
||||||
x := byte((re.cc[cc_i].ch0 >> (tmp*8)) & 0xFF)
|
x := byte((re.cc[cc_i].ch0 >> (tmp*8)) & 0xFF)
|
||||||
if x != 0 {
|
if x != 0 {
|
||||||
buf_ptr[i++] = x
|
unsafe {
|
||||||
|
buf_ptr[i++] = x
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tmp--
|
tmp--
|
||||||
}
|
}
|
||||||
|
@ -506,23 +511,31 @@ fn (re RE) get_char_class(pc int) string {
|
||||||
for tmp >= 0 {
|
for tmp >= 0 {
|
||||||
x := byte((re.cc[cc_i].ch0 >> (tmp*8)) & 0xFF)
|
x := byte((re.cc[cc_i].ch0 >> (tmp*8)) & 0xFF)
|
||||||
if x != 0 {
|
if x != 0 {
|
||||||
buf_ptr[i++] = x
|
unsafe {
|
||||||
|
buf_ptr[i++] = x
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tmp--
|
tmp--
|
||||||
}
|
}
|
||||||
buf_ptr[i++] = `-`
|
unsafe {
|
||||||
|
buf_ptr[i++] = `-`
|
||||||
|
}
|
||||||
tmp = 3
|
tmp = 3
|
||||||
for tmp >= 0 {
|
for tmp >= 0 {
|
||||||
x := byte((re.cc[cc_i].ch1 >> (tmp*8)) & 0xFF)
|
x := byte((re.cc[cc_i].ch1 >> (tmp*8)) & 0xFF)
|
||||||
if x != 0 {
|
if x != 0 {
|
||||||
buf_ptr[i++] = x
|
unsafe {
|
||||||
|
buf_ptr[i++] = x
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tmp--
|
tmp--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc_i++
|
cc_i++
|
||||||
}
|
}
|
||||||
buf_ptr[i] = byte(0)
|
unsafe {
|
||||||
|
buf_ptr[i] = byte(0)
|
||||||
|
}
|
||||||
|
|
||||||
return tos_clone( buf_ptr )
|
return tos_clone( buf_ptr )
|
||||||
}
|
}
|
||||||
|
@ -689,7 +702,9 @@ fn (re RE) parse_quantifier(in_txt string, in_i int) (int, int, int, bool) {
|
||||||
mut ch := byte(0)
|
mut ch := byte(0)
|
||||||
|
|
||||||
for i < in_txt.len {
|
for i < in_txt.len {
|
||||||
ch = in_txt.str[i]
|
unsafe {
|
||||||
|
ch = in_txt.str[i]
|
||||||
|
}
|
||||||
|
|
||||||
//println("${ch:c} status: $status")
|
//println("${ch:c} status: $status")
|
||||||
|
|
||||||
|
|
|
@ -2993,6 +2993,20 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
|
||||||
typ_sym.name.ends_with('ptr')) && !typ.has_flag(.variadic) { // byteptr, charptr etc
|
typ_sym.name.ends_with('ptr')) && !typ.has_flag(.variadic) { // byteptr, charptr etc
|
||||||
c.error('type `$typ_sym.name` does not support indexing', node.pos)
|
c.error('type `$typ_sym.name` does not support indexing', node.pos)
|
||||||
}
|
}
|
||||||
|
if !c.inside_unsafe && (typ.is_ptr() || typ.is_pointer()) {
|
||||||
|
mut is_ok := false
|
||||||
|
if node.left is ast.Ident {
|
||||||
|
ident := node.left as ast.Ident
|
||||||
|
scope := c.file.scope.innermost(ident.pos.pos)
|
||||||
|
if v := scope.find_var(ident.name) {
|
||||||
|
// `mut param []T` function parameter
|
||||||
|
is_ok = v.is_mut && v.is_arg && !typ.deref().is_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !is_ok {
|
||||||
|
c.warn('pointer indexing is only allowed in `unsafe` blocks', node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
if node.index !is ast.RangeExpr { // [1]
|
if node.index !is ast.RangeExpr { // [1]
|
||||||
index_type := c.expr(node.index)
|
index_type := c.expr(node.index)
|
||||||
c.check_index_type(typ_sym, index_type, node.pos)
|
c.check_index_type(typ_sym, index_type, node.pos)
|
||||||
|
|
|
@ -1,34 +1,48 @@
|
||||||
vlib/v/checker/tests/unsafe_required.v:4:6: error: pointer arithmetic is only allowed in `unsafe` blocks
|
vlib/v/checker/tests/unsafe_required.v:4:6: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||||
2 | v := 5
|
2 | v := 5
|
||||||
3 | mut p := &v
|
3 | mut p := &v
|
||||||
4 | p++
|
4 | p++
|
||||||
| ~~
|
| ~~
|
||||||
5 | p += 2
|
5 | p += 2
|
||||||
6 | _ := v
|
6 | _ := v
|
||||||
vlib/v/checker/tests/unsafe_required.v:5:7: error: pointer arithmetic is only allowed in `unsafe` blocks
|
vlib/v/checker/tests/unsafe_required.v:5:7: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||||
3 | mut p := &v
|
3 | mut p := &v
|
||||||
4 | p++
|
4 | p++
|
||||||
5 | p += 2
|
5 | p += 2
|
||||||
| ~~
|
| ~~
|
||||||
6 | _ := v
|
6 | _ := v
|
||||||
7 | }
|
7 | }
|
||||||
vlib/v/checker/tests/unsafe_required.v:11:14: error: pointer arithmetic is only allowed in `unsafe` blocks
|
vlib/v/checker/tests/unsafe_required.v:11:14: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||||
9 | fn test_ptr_infix() {
|
9 | fn test_ptr_infix() {
|
||||||
10 | v := 4
|
10 | v := 4
|
||||||
11 | mut q := &v - 1
|
11 | mut q := &v - 1
|
||||||
| ^
|
| ^
|
||||||
12 | q = q + 3
|
12 | q = q + 3
|
||||||
13 | _ := q
|
13 | _ := q
|
||||||
vlib/v/checker/tests/unsafe_required.v:12:9: error: pointer arithmetic is only allowed in `unsafe` blocks
|
vlib/v/checker/tests/unsafe_required.v:12:9: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||||
10 | v := 4
|
10 | v := 4
|
||||||
11 | mut q := &v - 1
|
11 | mut q := &v - 1
|
||||||
12 | q = q + 3
|
12 | q = q + 3
|
||||||
| ^
|
| ^
|
||||||
13 | _ := q
|
13 | _ := q
|
||||||
14 | _ := v
|
14 | _ := v
|
||||||
vlib/v/checker/tests/unsafe_required.v:24:7: error: method `S1.f` must be called from an `unsafe` block
|
vlib/v/checker/tests/unsafe_required.v:24:7: error: method `S1.f` must be called from an `unsafe` block
|
||||||
22 | fn test_funcs() {
|
22 | fn test_funcs() {
|
||||||
23 | s := S1{}
|
23 | s := S1{}
|
||||||
24 | s.f()
|
24 | s.f()
|
||||||
| ~~~
|
| ~~~
|
||||||
25 | }
|
25 | }
|
||||||
|
26 |
|
||||||
|
vlib/v/checker/tests/unsafe_required.v:32:7: error: pointer indexing is only allowed in `unsafe` blocks
|
||||||
|
30 | _ = b[0]
|
||||||
|
31 | c := &b
|
||||||
|
32 | _ = c[0]
|
||||||
|
| ~~~
|
||||||
|
33 |
|
||||||
|
34 | v := 4
|
||||||
|
vlib/v/checker/tests/unsafe_required.v:36:10: error: pointer indexing is only allowed in `unsafe` blocks
|
||||||
|
34 | v := 4
|
||||||
|
35 | p := &v
|
||||||
|
36 | _ = p[0]
|
||||||
|
| ~~~
|
||||||
|
37 | }
|
||||||
|
|
|
@ -23,3 +23,15 @@ fn test_funcs() {
|
||||||
s := S1{}
|
s := S1{}
|
||||||
s.f()
|
s.f()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_ptr_index(mut a []string) {
|
||||||
|
_ = a[0]
|
||||||
|
b := ['jo']
|
||||||
|
_ = b[0]
|
||||||
|
c := &b
|
||||||
|
_ = c[0]
|
||||||
|
|
||||||
|
v := 4
|
||||||
|
p := &v
|
||||||
|
_ = p[0]
|
||||||
|
}
|
||||||
|
|
|
@ -212,11 +212,13 @@ pub fn read_file(file_path string) ?string {
|
||||||
}
|
}
|
||||||
// BOM check
|
// BOM check
|
||||||
if raw_text.len >= 3 {
|
if raw_text.len >= 3 {
|
||||||
c_text := raw_text.str
|
unsafe {
|
||||||
if c_text[0] == 0xEF && c_text[1] == 0xBB && c_text[2] == 0xBF {
|
c_text := raw_text.str
|
||||||
// skip three BOM bytes
|
if c_text[0] == 0xEF && c_text[1] == 0xBB && c_text[2] == 0xBF {
|
||||||
offset_from_begin := 3
|
// skip three BOM bytes
|
||||||
raw_text = tos(c_text[offset_from_begin], vstrlen(c_text) - offset_from_begin)
|
offset_from_begin := 3
|
||||||
|
raw_text = tos(c_text[offset_from_begin], vstrlen(c_text) - offset_from_begin)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return raw_text
|
return raw_text
|
||||||
|
|
Loading…
Reference in New Issue