X-Git-Url: http://nitlanguage.org diff --git a/lib/core/file.nit b/lib/core/file.nit index 09b20d9..ed4c6c8 100644 --- a/lib/core/file.nit +++ b/lib/core/file.nit @@ -101,7 +101,6 @@ end # `Stream` that can read from a File class FileReader super FileStream - super BufferedReader super PollableReader # Misc @@ -114,62 +113,64 @@ class FileReader # assert l == f.read_line fun reopen do - if not eof and not _file.as(not null).address_is_null then close + 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}") - end_reached = true return end - end_reached = false - buffer_reset end - redef fun close + redef fun raw_read_byte do - super - buffer_reset - end_reached = true + 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 fill_buffer + redef fun raw_read_bytes(cstr, max) do - var nb = _file.as(not null).io_read(_buffer, _buffer_capacity) + 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_reached = true - end - if nb <= 0 then - end_reached = true - nb = 0 end - _buffer_length = nb - _buffer_pos = 0 + return nb end - # End of file? - redef var end_reached = false + 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.end_reached + # assert not f.eof # f.close # # In case of error, `last_error` is set # # f = new FileReader.open("/fail/does not/exist") - # assert f.end_reached + # assert f.eof # assert f.last_error != null init open(path: String) do self.path = path - prepare_buffer(100) _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_reached = true end end @@ -178,11 +179,9 @@ class FileReader # This is a low-level method. init from_fd(fd: Int) do self.path = "" - prepare_buffer(1) _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_reached = true end end @@ -210,13 +209,13 @@ class FileWriter super FileStream super Writer - redef fun write_bytes(s) do + redef fun write_bytes_from_cstring(cs, len) do if last_error != null then return if not _is_writable then last_error = new IOError("cannot write to non-writable stream") return end - write_native(s.items, 0, s.length) + write_native(cs, 0, len) end redef fun write(s) @@ -307,6 +306,9 @@ redef class Int private fun fd_to_stream(mode: CString): NativeFile `{ return fdopen((int)self, mode); `} + + # Does the file descriptor `self` refer to a terminal? + fun isatty: Bool `{ return isatty(self); `} end # Constant for read-only file streams @@ -330,7 +332,6 @@ class Stdin init do _file = new NativeFile.native_stdin path = "/dev/stdin" - prepare_buffer(1) end end @@ -510,9 +511,10 @@ class Path var input = open_ro var output = dest.open_wo + var buffer = new CString(4096) while not input.eof do - var buffer = input.read_bytes(1024) - output.write_bytes buffer + var read = input.read_bytes_to_cstring(buffer, 4096) + output.write_bytes_from_cstring(buffer, read) end input.close @@ -898,9 +900,7 @@ redef class Text # return true if a file with this names exists fun file_exists: Bool do return to_cstring.file_exists -end -redef class String # The status of a file. see POSIX stat(2). fun file_stat: nullable FileStat do @@ -943,14 +943,14 @@ redef class String if extension == null then extension = file_extension if extension == null then - return self + return self.to_s else extension = ".{extension}" end if has_suffix(extension) then - return substring(0, length - extension.length) + return substring(0, length - extension.length).to_s end - return self + return self.to_s end # Extract the basename of a path and strip the `extension` @@ -989,7 +989,7 @@ redef class String if extension != null then return n.strip_extension(extension) - else return n + else return n.to_s end # Extract the dirname of a path @@ -1018,7 +1018,7 @@ redef class String while l > 0 and s.chars[l] == '/' do l -= 1 # remove all trailing `/` var pos = s.chars.last_index_of_from('/', l) if pos > 0 then - return s.substring(0, pos) + return s.substring(0, pos).to_s else if pos == 0 then return "/" else @@ -1115,11 +1115,11 @@ redef class String # Note: You may want to use `simplify_path` on the result. # # Note: This method works only with POSIX paths. - fun join_path(path: String): String + fun join_path(path: Text): String do - if path.is_empty then return self - if self.is_empty then return path - if path.chars[0] == '/' then return path + if path.is_empty then return self.to_s + if self.is_empty then return path.to_s + if path.chars[0] == '/' then return path.to_s if self.last == '/' then return "{self}{path}" return "{self}/{path}" end @@ -1134,7 +1134,7 @@ redef class String # assert "".to_program_name == "./" # At least, your shell will detect the error. fun to_program_name: String do if self.has_prefix("/") then - return self + return self.to_s else return "./{self}" end @@ -1154,7 +1154,7 @@ redef class String # var b = "/bar" # var c = "baz/foobar" # assert a/b/c == "/bar/baz/foobar" - fun /(path: String): String do return join_path(path) + fun /(path: Text): String do return join_path(path) # Returns the relative path needed to go from `self` to `dest`. # @@ -1318,7 +1318,7 @@ redef class String do var last_slash = chars.last_index_of('.') if last_slash > 0 then - return substring( last_slash+1, length ) + return substring( last_slash+1, length ).to_s else return null end @@ -1365,7 +1365,7 @@ redef class FlatString var p = last_byte var c = its[p] var st = _first_byte - while p >= st and c != '.'.ascii do + while p >= st and c != u'.' do p -= 1 c = its[p] end @@ -1382,7 +1382,7 @@ redef class FlatString var l = s.last_byte var its = s._items var min = s._first_byte - var sl = '/'.ascii + var sl = u'/' while l > min and its[l] == sl do l -= 1 if l == min then return "/" var ns = l @@ -1526,7 +1526,7 @@ private extern class NativeFile `{ FILE* `} return (long)res; `} - fun write_byte(value: Byte): Int `{ + fun write_byte(value: Int): Int `{ unsigned char b = (unsigned char)value; return fwrite(&b, 1, 1, self); `} @@ -1545,6 +1545,8 @@ private extern class NativeFile `{ FILE* `} fun ferror: Bool `{ return ferror(self); `} + fun feof: Bool `{ return feof(self); `} + fun fileno: Int `{ return fileno(self); `} # Flushes the buffer, forcing the write operation