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
|
module os
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
|
mut:
|
||||||
cfile voidptr // Using void* instead of FILE*
|
cfile voidptr // Using void* instead of FILE*
|
||||||
pub:
|
pub:
|
||||||
fd int
|
fd int
|
||||||
@ -19,6 +20,18 @@ fn C._fseeki64(&C.FILE, u64, int) int
|
|||||||
|
|
||||||
fn C.getc(&C.FILE) 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.
|
// 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 {
|
pub fn open_file(path string, mode string, options ...int) ?File {
|
||||||
mut flags := 0
|
mut flags := 0
|
||||||
@ -55,10 +68,7 @@ pub fn open_file(path string, mode string, options ...int) ?File {
|
|||||||
permission = 0x0100 | 0x0080
|
permission = 0x0100 | 0x0080
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut p := path
|
p := fix_windows_path(path)
|
||||||
$if windows {
|
|
||||||
p = path.replace('/', '\\')
|
|
||||||
}
|
|
||||||
fd := C.open(&char(p.str), flags, permission)
|
fd := C.open(&char(p.str), flags, permission)
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
return error(posix_get_error_msg(C.errno))
|
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.
|
// read implements the Reader interface.
|
||||||
pub fn (f &File) read(mut buf []u8) ?int {
|
pub fn (f &File) read(mut buf []u8) ?int {
|
||||||
if buf.len == 0 {
|
if buf.len == 0 {
|
||||||
|
@ -1,5 +1,21 @@
|
|||||||
import os
|
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 {
|
struct Point {
|
||||||
x f64
|
x f64
|
||||||
y f64
|
y f64
|
||||||
@ -40,25 +56,6 @@ const (
|
|||||||
another_permission = Permissions.read | .write
|
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.
|
// 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
|
// 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
|
// 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
|
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() {
|
fn testsuite_end() {
|
||||||
os.chdir(os.wd_at_startup) or {}
|
os.chdir(os.wd_at_startup) or {}
|
||||||
os.rmdir_all(tfolder) or {}
|
os.rmdir_all(tfolder) or {}
|
||||||
assert !os.is_dir(tfolder)
|
// assert !os.is_dir(tfolder)
|
||||||
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user