os: add os.open_stdin/0 and os.File.get_line/0
parent
67cc515e74
commit
ce6d2759f5
|
@ -1,5 +1,7 @@
|
||||||
module os
|
module os
|
||||||
|
|
||||||
|
import strings
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
cfile voidptr // Using void* instead of FILE*
|
cfile voidptr // Using void* instead of FILE*
|
||||||
pub:
|
pub:
|
||||||
|
@ -88,3 +90,63 @@ pub fn (mut f File) flush() {
|
||||||
}
|
}
|
||||||
C.fflush(f.cfile)
|
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')
|
eprintln('os.executable() failed at reading /proc/curproc/exe to get exe path')
|
||||||
return executable_fallback()
|
return executable_fallback()
|
||||||
}
|
}
|
||||||
return result.vstring_with_len(count)
|
return unsafe { result.vstring_with_len(count) }
|
||||||
}
|
}
|
||||||
$if dragonfly {
|
$if dragonfly {
|
||||||
mut result := vcalloc(max_path_len)
|
mut result := vcalloc(max_path_len)
|
||||||
|
|
|
@ -43,6 +43,23 @@ fn test_open_file() {
|
||||||
os.rm(filename)
|
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() {
|
fn test_create_file() {
|
||||||
filename := './test1.txt'
|
filename := './test1.txt'
|
||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
|
|
Loading…
Reference in New Issue