mirror of
https://github.com/vlang/v.git
synced 2025-08-03 09:47:15 -04:00
107 lines
2.2 KiB
V
107 lines
2.2 KiB
V
module os
|
|
|
|
// low level operations with file descriptors/handles
|
|
|
|
$if !windows {
|
|
#include <sys/select.h>
|
|
}
|
|
|
|
$if windows {
|
|
#include <winsock2.h>
|
|
}
|
|
|
|
#flag windows -lws2_32
|
|
|
|
// fd_close closes the file descriptor. It returns 0 on success.
|
|
pub fn fd_close(fd int) int {
|
|
if fd == -1 {
|
|
return 0
|
|
}
|
|
return C.close(fd)
|
|
}
|
|
|
|
// fd_write writes the given string to the file descriptor.
|
|
// It blocks until all the data in the string is written.
|
|
pub fn fd_write(fd int, s string) {
|
|
if fd == -1 {
|
|
return
|
|
}
|
|
mut sp := s.str
|
|
mut remaining := s.len
|
|
for remaining > 0 {
|
|
written := C.write(fd, sp, remaining)
|
|
if written < 0 {
|
|
return
|
|
}
|
|
remaining = remaining - written
|
|
sp = unsafe { voidptr(sp + written) }
|
|
}
|
|
}
|
|
|
|
// fd_slurp reads all the remaining data from the file descriptor.
|
|
pub fn fd_slurp(fd int) []string {
|
|
mut res := []string{}
|
|
if fd == -1 {
|
|
return res
|
|
}
|
|
for {
|
|
s, b := fd_read(fd, 4096)
|
|
if b <= 0 {
|
|
break
|
|
}
|
|
res << s
|
|
}
|
|
return res
|
|
}
|
|
|
|
// fd_read reads data from the file descriptor. It returns the read data, and how many bytes were read.
|
|
pub fn fd_read(fd int, maxbytes int) (string, int) {
|
|
if fd == -1 {
|
|
return '', 0
|
|
}
|
|
unsafe {
|
|
mut buf := malloc_noscan(maxbytes + 1)
|
|
nbytes := C.read(fd, buf, maxbytes)
|
|
if nbytes < 0 {
|
|
free(buf)
|
|
return '', nbytes
|
|
}
|
|
buf[nbytes] = 0
|
|
return tos(buf, nbytes), nbytes
|
|
}
|
|
}
|
|
|
|
[typedef]
|
|
pub struct C.fd_set {}
|
|
|
|
pub struct C.timeval {
|
|
tv_sec u64
|
|
tv_usec u64
|
|
}
|
|
|
|
fn C.@select(ndfs int, readfds &C.fd_set, writefds &C.fd_set, exceptfds &C.fd_set, timeout &C.timeval) int
|
|
|
|
// These are C macros, but from the V's point of view, can be treated as C functions:
|
|
fn C.FD_ZERO(fdset &C.fd_set)
|
|
fn C.FD_SET(fd int, fdset &C.fd_set)
|
|
fn C.FD_ISSET(fd int, fdset &C.fd_set) int
|
|
|
|
// fd_is_pending returns true, when there is pending data, waiting to be read from file descriptor `fd`.
|
|
// If the file descriptor is closed, or if reading from it, will block (there is no data), fd_is_pending returns false.
|
|
pub fn fd_is_pending(fd int) bool {
|
|
read_set := C.fd_set{}
|
|
C.FD_ZERO(&read_set)
|
|
C.FD_SET(fd, &read_set)
|
|
mut ts := C.timeval{
|
|
tv_sec: 0
|
|
tv_usec: 0
|
|
}
|
|
res := C.@select(fd + 1, &read_set, C.NULL, C.NULL, &ts)
|
|
if res > 0 {
|
|
if C.FD_ISSET(fd, &read_set) != 0 {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|