Merge: nitdoc: full rewrite
[nit.git] / lib / core / file.nit
index 643fe08..ed4c6c8 100644 (file)
@@ -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
@@ -1363,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
@@ -1380,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
@@ -1524,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);
        `}
@@ -1543,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