Skip to content

Commit 12731cc

Browse files
rrthomasspytheman
authored andcommitted
file: bind freopen and feof as File methods
1 parent 3d0a48b commit 12731cc

2 files changed

Lines changed: 49 additions & 4 deletions

File tree

vlib/os/file.c.v

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module os
22

33
pub struct File {
4+
mut:
45
cfile voidptr // Using void* instead of FILE*
56
pub:
67
fd int
@@ -19,6 +20,16 @@ fn C._fseeki64(&C.FILE, u64, int) int
1920

2021
fn C.getc(&C.FILE) int
2122

23+
fn C.freopen(&char, &char, &C.FILE) &C.FILE
24+
25+
fn fix_windows_path(path string) string {
26+
mut p := path
27+
$if windows {
28+
p = path.replace('/', '\\')
29+
}
30+
return p
31+
}
32+
2233
// open_file can be used to open or create a file with custom flags and permissions and returns a `File` object.
2334
pub fn open_file(path string, mode string, options ...int) ?File {
2435
mut flags := 0
@@ -55,10 +66,7 @@ pub fn open_file(path string, mode string, options ...int) ?File {
5566
permission = 0x0100 | 0x0080
5667
}
5768
}
58-
mut p := path
59-
$if windows {
60-
p = path.replace('/', '\\')
61-
}
69+
p := fix_windows_path(path)
6270
fd := C.open(&char(p.str), flags, permission)
6371
if fd == -1 {
6472
return error(posix_get_error_msg(C.errno))
@@ -160,6 +168,20 @@ pub fn stderr() File {
160168
}
161169
}
162170

171+
pub fn (f &File) eof() bool {
172+
return C.feof(f.cfile) != 0
173+
}
174+
175+
// reopen allows a `File` to be reused. It is mostly useful for reopening standard input and output.
176+
pub fn (mut f File) reopen(path string, mode string) ? {
177+
p := fix_windows_path(path)
178+
cfile := C.freopen(&char(p.str), &char(mode.str), f.cfile)
179+
if isnil(cfile) {
180+
return error('Failed to reopen file "$path"')
181+
}
182+
f.cfile = cfile
183+
}
184+
163185
// read implements the Reader interface.
164186
pub fn (f &File) read(mut buf []u8) ?int {
165187
if buf.len == 0 {

vlib/os/file_test.v

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,26 @@ fn test_tell() ? {
370370
assert pos == size - 5
371371
}
372372
}
373+
374+
fn test_reopen() ? {
375+
mut f := os.open_file(tfile, 'w')?
376+
f.write_string('Hello World!\nGood\r morning.')?
377+
f.close()
378+
379+
mut stdin := os.stdin()
380+
stdin.reopen(tfile, 'r')?
381+
line := os.get_line()
382+
assert line == 'Hello World!'
383+
}
384+
385+
fn test_eof() ? {
386+
mut f := os.open_file(tfile, 'w')?
387+
f.write_string('Hello World!\n')?
388+
f.close()
389+
390+
f = os.open(tfile)?
391+
f.read_bytes(10)
392+
assert !f.eof()
393+
f.read_bytes(100)
394+
assert f.eof()
395+
}

0 commit comments

Comments
 (0)