core :: FileReader :: defaultinit
# `Stream` that can read from a File
class FileReader
super FileStream
super PollableReader
# Misc
# Open the same file again.
# The original path is reused, therefore the reopened file can be a different file.
#
# var f = new FileReader.open("/etc/issue")
# var l = f.read_line
# f.reopen
# assert l == f.read_line
fun reopen
do
var fl = _file
if fl != null and not fl.address_is_null then close
last_error = null
_file = new NativeFile.io_open_read(path.as(not null).to_cstring)
if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path.as(not null)}`: {sys.errno.strerror}")
return
end
end
redef fun raw_read_byte
do
var nb = _file.as(not null).io_read(write_buffer, 1)
if last_error == null and _file.as(not null).ferror then
last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
end
if nb == 0 then return -1
return write_buffer[0].to_i
end
redef fun raw_read_bytes(cstr, max)
do
var nb = _file.as(not null).io_read(cstr, max)
if last_error == null and _file.as(not null).ferror then
last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
end
return nb
end
redef fun eof do
var fl = _file
if fl == null then return true
if fl.address_is_null then return true
if last_error != null then return true
if super then
if last_error != null then return true
return fl.feof
end
return false
end
# Open the file at `path` for reading.
#
# var f = new FileReader.open("/etc/issue")
# assert not f.eof
# f.close
#
# In case of error, `last_error` is set
#
# f = new FileReader.open("/fail/does not/exist")
# assert f.eof
# assert f.last_error != null
init open(path: String)
do
self.path = path
_file = new NativeFile.io_open_read(path.to_cstring)
if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
end
end
# Creates a new File stream from a file descriptor
#
# This is a low-level method.
init from_fd(fd: Int) do
self.path = ""
_file = fd.fd_to_stream(read_only)
if _file.as(not null).address_is_null then
last_error = new IOError("Error: Converting fd {fd} to stream failed with '{sys.errno.strerror}'")
end
end
redef fun poll_in
do
var res = native_poll_in(fd)
if res == -1 then
last_error = new IOError(errno.to_s)
return false
else return res > 0
end
private fun native_poll_in(fd: Int): Int `{
#ifndef _WIN32
struct pollfd fds = {(int)fd, POLLIN, 0};
return poll(&fds, 1, 0);
#else
return 0;
#endif
`}
end
lib/core/file.nit:101,1--205,3