os: add os.open_stdin/0 and os.File.get_line/0
parent
67cc515e74
commit
ce6d2759f5
|
@ -1,5 +1,7 @@
|
|||
module os
|
||||
|
||||
import strings
|
||||
|
||||
pub struct File {
|
||||
cfile voidptr // Using void* instead of FILE*
|
||||
pub:
|
||||
|
@ -88,3 +90,63 @@ pub fn (mut f File) flush() {
|
|||
}
|
||||
C.fflush(f.cfile)
|
||||
}
|
||||
|
||||
// open_stdin - return an os.File for stdin, so that you can use .get_line on it too.
|
||||
pub fn open_stdin() File {
|
||||
return File{
|
||||
fd: 0
|
||||
cfile: C.stdin
|
||||
is_opened: true
|
||||
}
|
||||
}
|
||||
|
||||
// File.get_line - get a single line from the file. NB: the ending newline is *included*.
|
||||
pub fn (mut f File) get_line() ?string {
|
||||
if !f.is_opened {
|
||||
return error('file is closed')
|
||||
}
|
||||
$if !windows {
|
||||
mut zbuf := byteptr(0)
|
||||
mut zblen := size_t(0)
|
||||
mut zx := 0
|
||||
unsafe {
|
||||
zx = C.getline(&zbuf, &zblen, f.cfile)
|
||||
if zx == -1 {
|
||||
C.free(zbuf)
|
||||
if C.errno == 0 {
|
||||
return error('end of file')
|
||||
}
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
return zbuf.vstring_with_len(zx)
|
||||
}
|
||||
}
|
||||
//
|
||||
// using C.fgets is less efficient than f.get_line_getline,
|
||||
// but is available everywhere, while C.getline does not work
|
||||
// on windows
|
||||
//
|
||||
buf := [4096]byte{}
|
||||
mut res := strings.new_builder(1024)
|
||||
mut x := 0
|
||||
for {
|
||||
unsafe {
|
||||
x = C.fgets(charptr(buf), 4096, f.cfile)
|
||||
}
|
||||
if x == 0 {
|
||||
if res.len > 0 {
|
||||
break
|
||||
}
|
||||
return error('end of file')
|
||||
}
|
||||
bufbp := byteptr(buf)
|
||||
mut blen := vstrlen(bufbp)
|
||||
res.write_bytes(bufbp, blen)
|
||||
unsafe {
|
||||
if blen == 0 || bufbp[blen-1] == `\n` || bufbp[blen-1] == `\r` {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return res.str()
|
||||
}
|
||||
|
|
|
@ -928,7 +928,7 @@ pub fn executable() string {
|
|||
eprintln('os.executable() failed at reading /proc/curproc/exe to get exe path')
|
||||
return executable_fallback()
|
||||
}
|
||||
return result.vstring_with_len(count)
|
||||
return unsafe { result.vstring_with_len(count) }
|
||||
}
|
||||
$if dragonfly {
|
||||
mut result := vcalloc(max_path_len)
|
||||
|
|
|
@ -43,6 +43,23 @@ fn test_open_file() {
|
|||
os.rm(filename)
|
||||
}
|
||||
|
||||
fn test_file_get_line() {
|
||||
filename := './fgetline.txt'
|
||||
os.write_file(filename, 'line 1\nline 2')
|
||||
mut f := os.open_file(filename, 'r', 0) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
line1 := f.get_line() or { '' }
|
||||
line2 := f.get_line() or { '' }
|
||||
f.close()
|
||||
//
|
||||
//eprintln('line1: $line1')
|
||||
//eprintln('line2: $line2')
|
||||
assert line1 == 'line 1\n'
|
||||
assert line2 == 'line 2'
|
||||
}
|
||||
|
||||
fn test_create_file() {
|
||||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
|
|
Loading…
Reference in New Issue