mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
os: add File.reopen and File.eof methods (#15184)
This commit is contained in:
parent
3d0a48b1bb
commit
ed56c3957e
@ -1,6 +1,7 @@
|
||||
module os
|
||||
|
||||
pub struct File {
|
||||
mut:
|
||||
cfile voidptr // Using void* instead of FILE*
|
||||
pub:
|
||||
fd int
|
||||
@ -19,6 +20,18 @@ fn C._fseeki64(&C.FILE, u64, int) int
|
||||
|
||||
fn C.getc(&C.FILE) int
|
||||
|
||||
fn C.freopen(&char, &char, &C.FILE) &C.FILE
|
||||
|
||||
fn C._wfreopen(&u16, &u16, &C.FILE) &C.FILE
|
||||
|
||||
fn fix_windows_path(path string) string {
|
||||
mut p := path
|
||||
$if windows {
|
||||
p = path.replace('/', '\\')
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// open_file can be used to open or create a file with custom flags and permissions and returns a `File` object.
|
||||
pub fn open_file(path string, mode string, options ...int) ?File {
|
||||
mut flags := 0
|
||||
@ -55,10 +68,7 @@ pub fn open_file(path string, mode string, options ...int) ?File {
|
||||
permission = 0x0100 | 0x0080
|
||||
}
|
||||
}
|
||||
mut p := path
|
||||
$if windows {
|
||||
p = path.replace('/', '\\')
|
||||
}
|
||||
p := fix_windows_path(path)
|
||||
fd := C.open(&char(p.str), flags, permission)
|
||||
if fd == -1 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
@ -160,6 +170,26 @@ pub fn stderr() File {
|
||||
}
|
||||
}
|
||||
|
||||
// eof returns true, when the end of file has been reached
|
||||
pub fn (f &File) eof() bool {
|
||||
return C.feof(f.cfile) != 0
|
||||
}
|
||||
|
||||
// reopen allows a `File` to be reused. It is mostly useful for reopening standard input and output.
|
||||
pub fn (mut f File) reopen(path string, mode string) ? {
|
||||
p := fix_windows_path(path)
|
||||
mut cfile := &C.FILE(0)
|
||||
$if windows {
|
||||
cfile = C._wfreopen(p.to_wide(), mode.to_wide(), f.cfile)
|
||||
} $else {
|
||||
cfile = C.freopen(&char(p.str), &char(mode.str), f.cfile)
|
||||
}
|
||||
if isnil(cfile) {
|
||||
return error('Failed to reopen file "$path"')
|
||||
}
|
||||
f.cfile = cfile
|
||||
}
|
||||
|
||||
// read implements the Reader interface.
|
||||
pub fn (f &File) read(mut buf []u8) ?int {
|
||||
if buf.len == 0 {
|
||||
|
@ -1,5 +1,21 @@
|
||||
import os
|
||||
|
||||
const tfolder = os.join_path(os.temp_dir(), 'v', 'tests', 'os_file_test')
|
||||
|
||||
const tfile = os.join_path_single(tfolder, 'test_file')
|
||||
|
||||
fn testsuite_begin() ? {
|
||||
os.rmdir_all(tfolder) or {}
|
||||
assert !os.is_dir(tfolder)
|
||||
os.mkdir_all(tfolder)?
|
||||
os.chdir(tfolder)?
|
||||
assert os.is_dir(tfolder)
|
||||
}
|
||||
|
||||
fn testsuite_end() ? {
|
||||
os.rmdir_all(tfolder) or {}
|
||||
}
|
||||
|
||||
struct Point {
|
||||
x f64
|
||||
y f64
|
||||
@ -40,25 +56,6 @@ const (
|
||||
another_permission = Permissions.read | .write
|
||||
)
|
||||
|
||||
const (
|
||||
tfolder = os.join_path_single(os.temp_dir(), 'os_file_test')
|
||||
tfile = os.join_path_single(tfolder, 'test_file')
|
||||
)
|
||||
|
||||
fn testsuite_begin() ? {
|
||||
os.rmdir_all(tfolder) or {}
|
||||
assert !os.is_dir(tfolder)
|
||||
os.mkdir_all(tfolder)?
|
||||
os.chdir(tfolder)?
|
||||
assert os.is_dir(tfolder)
|
||||
}
|
||||
|
||||
fn testsuite_end() ? {
|
||||
os.chdir(os.wd_at_startup)?
|
||||
os.rmdir_all(tfolder)?
|
||||
assert !os.is_dir(tfolder)
|
||||
}
|
||||
|
||||
// test_read_bytes_into_newline_text tests reading text from a file with newlines.
|
||||
// This test simulates reading a larger text file step by step into a buffer and
|
||||
// returning on each newline, even before the buffer is full, and reaching EOF before
|
||||
@ -370,3 +367,42 @@ fn test_tell() ? {
|
||||
assert pos == size - 5
|
||||
}
|
||||
}
|
||||
|
||||
fn test_reopen() ? {
|
||||
tfile1 := os.join_path_single(tfolder, 'tfile1')
|
||||
tfile2 := os.join_path_single(tfolder, 'tfile2')
|
||||
os.write_file(tfile1, 'Hello World!\nGood\r morning.\nBye 1.')?
|
||||
os.write_file(tfile2, 'Another file\nAnother line.\nBye 2.')?
|
||||
assert os.file_size(tfile1) > 0
|
||||
assert os.file_size(tfile2) > 0
|
||||
|
||||
mut line_buffer := []u8{len: 1024}
|
||||
|
||||
mut f2 := os.open(tfile2)?
|
||||
x := f2.read_bytes_into_newline(mut line_buffer)?
|
||||
assert !f2.eof()
|
||||
assert x > 0
|
||||
assert line_buffer#[..x].bytestr() == 'Another file\n'
|
||||
|
||||
// Note: after this call, f2 should be using the file `tfile1`:
|
||||
f2.reopen(tfile1, 'r')?
|
||||
assert !f2.eof()
|
||||
|
||||
z := f2.read(mut line_buffer)?
|
||||
assert f2.eof()
|
||||
assert z > 0
|
||||
content := line_buffer#[..z].bytestr()
|
||||
// dump(content)
|
||||
assert content.starts_with('Hello World')
|
||||
assert content.ends_with('Bye 1.')
|
||||
}
|
||||
|
||||
fn test_eof() ? {
|
||||
os.write_file(tfile, 'Hello World!\n')?
|
||||
|
||||
mut f := os.open(tfile)?
|
||||
f.read_bytes(10)
|
||||
assert !f.eof()
|
||||
f.read_bytes(100)
|
||||
assert f.eof()
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ fn testsuite_begin() {
|
||||
fn testsuite_end() {
|
||||
os.chdir(os.wd_at_startup) or {}
|
||||
os.rmdir_all(tfolder) or {}
|
||||
assert !os.is_dir(tfolder)
|
||||
// assert !os.is_dir(tfolder)
|
||||
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user