os: cleanup code duplication for os.create and os.open

pull/4934/head
Delyan Angelov 2020-05-19 13:38:06 +03:00
parent 03525843a0
commit 931c846602
4 changed files with 118 additions and 146 deletions

View File

@ -54,6 +54,9 @@ fn C.fseek() int
fn C.fopen() voidptr
fn C.fileno(voidptr) int
fn C.fwrite() int

View File

@ -223,7 +223,10 @@ pub fn mv_by_cp(source string, target string) ?bool {
return true
}
fn vfopen(path, mode string) &C.FILE {
// vfopen returns an opened C file, given its path and open mode.
// NB: os.vfopen is useful for compatibility with C libraries, that expect `FILE *`.
// If you write pure V code, os.create or os.open are more convenient.
pub fn vfopen(path, mode string) &C.FILE {
$if windows {
return C._wfopen(path.to_wide(), mode.to_wide())
} $else {
@ -231,6 +234,15 @@ fn vfopen(path, mode string) &C.FILE {
}
}
// fileno returns the file descriptor of an opened C file
pub fn fileno(cfile voidptr) int {
$if windows {
return C._fileno(cfile)
} $else {
return C.fileno(cfile)
}
}
// read_lines reads the file in `path` into an array of lines.
pub fn read_lines(path string) ?[]string {
buf := read_file(path) or {
@ -1246,3 +1258,102 @@ pub fn resource_abs_path(path string) string {
}
return os.real_path(os.join_path(base_path, path))
}
// open tries to open a file for reading and returns back a read-only `File` object
pub fn open(path string) ?File {
/*
$if linux {
$if !android {
fd := C.syscall(sys_open, path.str, 511)
if fd == -1 {
return error('failed to open file "$path"')
}
return File{
fd: fd
opened: true
}
}
}
*/
cfile := vfopen(path, 'rb')
if cfile == 0 {
return error('failed to open file "$path"')
}
fd := fileno(cfile)
return File {
cfile: cfile
fd: fd
opened: true
}
}
// create creates or opens a file at a specified location and returns a write-only `File` object
pub fn create(path string) ?File {
/*
// NB: android/termux/bionic is also a kind of linux,
// but linux syscalls there sometimes fail,
// while the libc version should work.
$if linux {
$if !android {
//$if macos {
// fd = C.syscall(398, path.str, 0x601, 0x1b6)
//}
//$if linux {
fd = C.syscall(sys_creat, path.str, 511)
//}
if fd == -1 {
return error('failed to create file "$path"')
}
file = File{
fd: fd
opened: true
}
return file
}
}
*/
cfile := vfopen(path, 'wb')
if cfile == 0 {
return error('failed to create file "$path"')
}
fd := fileno(cfile)
return File {
cfile: cfile
fd: fd
opened: true
}
}
pub fn (mut f File) write(s string) {
if !f.opened {
return
}
/*
$if linux {
$if !android {
C.syscall(sys_write, f.fd, s.str, s.len)
return
}
}
*/
C.fputs(s.str, f.cfile)
}
pub fn (mut f File) writeln(s string) {
if !f.opened {
return
}
/*
$if linux {
$if !android {
snl := s + '\n'
C.syscall(sys_write, f.fd, snl.str, snl.len)
return
}
}
*/
// TODO perf
C.fputs(s.str, f.cfile)
C.fputs('\n', f.cfile)
}

View File

@ -66,112 +66,12 @@ pub fn is_dir(path string) bool {
}
*/
// open opens a file at the specified and returns back a read-only `File` object
pub fn open(path string) ?File {
/*
$if linux {
$if !android {
fd := C.syscall(sys_open, path.str, 511)
if fd == -1 {
return error('failed to open file "$path"')
}
return File{
fd: fd
opened: true
}
}
}
*/
file := File{
cfile: C.fopen(charptr(path.str), 'rb')
fd: 0
opened: true
}
if isnil(file.cfile) {
return error('failed to open file "$path"')
}
return file
}
// create creates or opens a file at a specified location and returns a write-only `File` object
pub fn create(path string) ?File {
/*
// NB: android/termux/bionic is also a kind of linux,
// but linux syscalls there sometimes fail,
// while the libc version should work.
$if linux {
$if !android {
//$if macos {
// fd = C.syscall(398, path.str, 0x601, 0x1b6)
//}
//$if linux {
fd = C.syscall(sys_creat, path.str, 511)
//}
if fd == -1 {
return error('failed to create file "$path"')
}
file = File{
fd: fd
opened: true
}
return file
}
}
*/
file := File{
cfile: C.fopen(charptr(path.str), 'wb')
fd: 0
opened: true
}
if isnil(file.cfile) {
return error('failed to create file "$path"')
}
return file
}
/*
pub fn (mut f File) fseek(pos, mode int) {
}
*/
pub fn (mut f File) write(s string) {
if !f.opened {
return
}
/*
$if linux {
$if !android {
C.syscall(sys_write, f.fd, s.str, s.len)
return
}
}
*/
C.fputs(s.str, f.cfile)
// C.fwrite(s.str, 1, s.len, f.cfile)
}
pub fn (mut f File) writeln(s string) {
if !f.opened {
return
}
/*
$if linux {
$if !android {
snl := s + '\n'
C.syscall(sys_write, f.fd, snl.str, snl.len)
return
}
}
*/
// C.fwrite(s.str, 1, s.len, f.cfile)
// ss := s.clone()
// TODO perf
C.fputs(s.str, f.cfile)
// ss.free()
C.fputs('\n', f.cfile)
}
// mkdir creates a new directory with the specified path.
pub fn mkdir(path string) ?bool {
if path == '.' {

View File

@ -130,47 +130,6 @@ pub fn is_dir(path string) bool {
}
*/
pub fn open(path string) ?File {
mode := 'rb'
file := File {
cfile: C._wfopen(path.to_wide(), mode.to_wide())
opened: true
}
if isnil(file.cfile) {
return error('failed to open file "$path"')
}
return file
}
// create creates a file at a specified location and returns a writable `File` object.
pub fn create(path string) ?File {
mode := 'wb'
file := File {
cfile: C._wfopen(path.to_wide(), mode.to_wide())
opened: true
}
if isnil(file.cfile) {
return error('failed to create file "$path"')
}
return file
}
pub fn (mut f File) write(s string) {
if !f.opened {
return
}
C.fputs(s.str, f.cfile)
}
pub fn (mut f File) writeln(s string) {
if !f.opened {
return
}
// TODO perf
C.fputs(s.str, f.cfile)
C.fputs('\n', f.cfile)
}
// mkdir creates a new directory with the specified path.
pub fn mkdir(path string) ?bool {
@ -185,12 +144,11 @@ pub fn mkdir(path string) ?bool {
// Ref - https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=vs-2019
// get_file_handle retrieves the operating-system file handle that is associated with the specified file descriptor.
pub fn get_file_handle(path string) HANDLE {
mode := 'rb'
fd := C._wfopen(path.to_wide(), mode.to_wide())
if fd == 0 {
cfile := vfopen(path, 'rb')
if cfile == 0 {
return HANDLE(INVALID_HANDLE_VALUE)
}
handle := HANDLE(C._get_osfhandle(C._fileno(fd))) // CreateFile? - hah, no -_-
handle := HANDLE(C._get_osfhandle(fileno(cfile))) // CreateFile? - hah, no -_-
return handle
}