X-Git-Url: http://nitlanguage.org diff --git a/lib/standard/stream.nit b/lib/standard/stream.nit index 88a73ac..745064a 100644 --- a/lib/standard/stream.nit +++ b/lib/standard/stream.nit @@ -10,11 +10,18 @@ # You are allowed to redistribute it and sell it, alone or is a part of # another product. -# This module handle abstract input and output streams -package stream +# Input and output streams of characters +module stream import string +in "C" `{ + #include + #include + #include + #include +`} + # Abstract stream class interface IOS # close the stream @@ -61,7 +68,7 @@ interface IStream return s.to_s end - # Read a string until the end of the line and append it to `s'. + # Read a string until the end of the line and append it to `s`. fun append_line_to(s: Buffer) do loop @@ -70,13 +77,14 @@ interface IStream if eof then return else var c = x.ascii - s.push(c) + s.chars.push(c) if c == '\n' then return end end end # Is there something to read. + # This function returns 'false' if there is something to read. fun eof: Bool is abstract end @@ -102,7 +110,7 @@ abstract class BufferedIStream if _buffer_pos >= _buffer.length then return -1 end - var c = _buffer[_buffer_pos] + var c = _buffer.chars[_buffer_pos] _buffer_pos += 1 return c.ascii end @@ -120,7 +128,7 @@ abstract class BufferedIStream k = _buffer.length end while j < k and i > 0 do - s.add(_buffer[j]) + s.add(_buffer.chars[j]) j += 1 i -= 1 end @@ -136,7 +144,7 @@ abstract class BufferedIStream var j = _buffer_pos var k = _buffer.length while j < k do - s.add(_buffer[j]) + s.add(_buffer.chars[j]) j += 1 end _buffer_pos = j @@ -150,7 +158,7 @@ abstract class BufferedIStream loop # First phase: look for a '\n' var i = _buffer_pos - while i < _buffer.length and _buffer[i] != '\n' do i += 1 + while i < _buffer.length and _buffer.chars[i] != '\n' do i += 1 # if there is something to append if i > _buffer_pos then @@ -160,7 +168,7 @@ abstract class BufferedIStream # Copy from the buffer to the string var j = _buffer_pos while j < i do - s.add(_buffer[j]) + s.add(_buffer.chars[j]) j += 1 end end @@ -195,7 +203,7 @@ abstract class BufferedIStream # Is the last fill_buffer reach the end protected fun end_reached: Bool is abstract - # Allocate a `_buffer' for a given `capacity'. + # Allocate a `_buffer` for a given `capacity`. protected fun prepare_buffer(capacity: Int) do _buffer = new Buffer.with_capacity(capacity) @@ -213,27 +221,28 @@ end abstract class FDStream super IOS # File description - var _fd: Int + var fd: Int - redef fun close do native_close(_fd) + redef fun close do native_close(fd) private fun native_close(i: Int): Int is extern "stream_FDStream_FDStream_native_close_1" private fun native_read_char(i: Int): Int is extern "stream_FDStream_FDStream_native_read_char_1" private fun native_read(i: Int, buf: NativeString, len: Int): Int is extern "stream_FDStream_FDStream_native_read_3" private fun native_write(i: Int, buf: NativeString, len: Int): Int is extern "stream_FDStream_FDStream_native_write_3" + private fun native_write_char(i: Int, c: Char): Int is extern "stream_FDStream_FDStream_native_write_char_2" - init(fd: Int) do _fd = fd + init(fd: Int) do self.fd = fd end class FDIStream super FDStream super IStream - redef readable var _eof: Bool = false + redef var eof: Bool = false redef fun read_char do - var nb = native_read_char(_fd) - if nb == -1 then _eof = true + var nb = native_read_char(fd) + if nb == -1 then eof = true return nb end @@ -243,17 +252,17 @@ end class FDOStream super FDStream super OStream - redef readable var _is_writable: Bool + redef var is_writable: Bool redef fun write(s) do - var nb = native_write(_fd, s.to_cstring, s.length) - if nb < s.length then _is_writable = false + var nb = native_write(fd, s.to_cstring, s.length) + if nb < s.length then is_writable = false end init(fd: Int) do - _is_writable = true + is_writable = true end end @@ -263,7 +272,95 @@ class FDIOStream super IOStream init(fd: Int) do - _fd = fd - _is_writable = true + self.fd = fd + is_writable = true + end +end + +redef interface Object + # returns first available stream to read or write to + # return null on interruption (possibly a signal) + protected fun poll( streams : Sequence[FDStream] ) : nullable FDStream + do + var in_fds = new Array[Int] + var out_fds = new Array[Int] + var fd_to_stream = new HashMap[Int,FDStream] + for s in streams do + var fd = s.fd + if s isa FDIStream then in_fds.add( fd ) + if s isa FDOStream then out_fds.add( fd ) + + fd_to_stream[fd] = s + end + + var polled_fd = intern_poll( in_fds, out_fds ) + + if polled_fd == null then + return null + else + return fd_to_stream[polled_fd] + end end + + private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]) : nullable Int is extern import Array[Int].length, Array[Int].[], Int.as(nullable Int) `{ + int in_len, out_len, total_len; + struct pollfd *c_fds; + sigset_t sigmask; + int i; + int first_polled_fd = -1; + int result; + + in_len = Array_of_Int_length( in_fds ); + out_len = Array_of_Int_length( out_fds ); + total_len = in_len + out_len; + c_fds = malloc( sizeof(struct pollfd) * total_len ); + + /* input streams */ + for ( i=0; i 0 ) { + /* analyse results */ + for ( i=0; i