X-Git-Url: http://nitlanguage.org diff --git a/lib/standard/stream.nit b/lib/standard/stream.nit index d65d377..6765305 100644 --- a/lib/standard/stream.nit +++ b/lib/standard/stream.nit @@ -1,25 +1,24 @@ # This file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2004-2008 Jean Privat -# -# This file is free software, which comes along with NIT. This software is +# This file is free software, which comes along with NIT. This software is # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. You can modify it is you want, provided this header +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. You can modify it is you want, provided this header # is kept unaltered, and a notification of the changes is added. -# You are allowed to redistribute it and sell it, alone or is a part of +# You are allowed to redistribute it and sell it, alone or is a part of # another product. # Input and output streams of characters module stream -import string +intrude import ropes in "C" `{ #include #include #include #include + #include `} # Abstract stream class @@ -88,11 +87,20 @@ interface IStream fun eof: Bool is abstract end +# IStream capable of declaring if readable without blocking +interface PollableIStream + super IStream + + # Is there something to read? (without blocking) + fun poll_in: Bool is abstract + +end + # Abstract output stream interface OStream super IOS # write a string - fun write(s: String) is abstract + fun write(s: Text) is abstract # Can the stream be used to write fun is_writable: Bool is abstract @@ -122,11 +130,34 @@ interface Streamable end end -redef class String +redef class Text super Streamable redef fun write_to(stream) do stream.write(self) end +redef class RopeNode + super Streamable +end + +redef class Leaf + + redef fun write_to(s) do s.write(str) +end + +redef class Concat + + redef fun write_to(s) + do + if left != null then left.write_to(s) + if right != null then right.write_to(s) + end +end + +redef class RopeString + + redef fun write_to(s) do root.write_to(s) +end + # Input streams with a buffer abstract class BufferedIStream super IStream @@ -146,24 +177,20 @@ abstract class BufferedIStream redef fun read(i) do - var s = new FlatBuffer.with_capacity(i) - var j = _buffer_pos - var k = _buffer.length - while i > 0 do - if j >= k then + if _buffer.length == _buffer_pos then + if not eof then fill_buffer - if eof then return s.to_s - j = _buffer_pos - k = _buffer.length - end - while j < k and i > 0 do - s.add(_buffer.chars[j]) - j += 1 - i -= 1 + return read(i) end + return "" end - _buffer_pos = j - return s.to_s + if _buffer_pos + i >= _buffer.length then + var from = _buffer_pos + _buffer_pos = _buffer.length + return _buffer.substring_from(from).to_s + end + _buffer_pos += i + return _buffer.substring(_buffer_pos - i, i).to_s end redef fun read_all @@ -173,14 +200,14 @@ abstract class BufferedIStream var j = _buffer_pos var k = _buffer.length while j < k do - s.add(_buffer.chars[j]) + s.add(_buffer[j]) j += 1 end _buffer_pos = j fill_buffer end return s.to_s - end + end redef fun append_line_to(s) do @@ -221,15 +248,15 @@ abstract class BufferedIStream redef fun eof do return _buffer_pos >= _buffer.length and end_reached # The buffer - var _buffer: nullable FlatBuffer = null + private var buffer: nullable FlatBuffer = null # The current position in the buffer - var _buffer_pos: Int = 0 + private var buffer_pos: Int = 0 # Fill the buffer protected fun fill_buffer is abstract - # Is the last fill_buffer reach the end + # Is the last fill_buffer reach the end protected fun end_reached: Bool is abstract # Allocate a `_buffer` for a given `capacity`. @@ -259,8 +286,6 @@ abstract class FDStream 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 self.fd = fd end class FDIStream @@ -274,36 +299,24 @@ class FDIStream if nb == -1 then eof = true return nb end - - init(fd: Int) do end end class FDOStream super FDStream super OStream - redef var is_writable: Bool + redef var is_writable = true redef fun write(s) do 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 - end end class FDIOStream super FDIStream super FDOStream super IOStream - init(fd: Int) - do - self.fd = fd - is_writable = true - end end redef interface Object @@ -384,12 +397,51 @@ redef interface Object `} end -# Stream to a String. Mainly used for compatibility with OStream type and tests. +# Stream to a String. +# +# Mainly used for compatibility with OStream type and tests. class StringOStream super OStream private var content = new Array[String] redef fun to_s do return content.to_s - redef fun is_writable do return true - redef fun write(str) do content.add(str) + redef fun is_writable do return not closed + redef fun write(str) + do + assert not closed + content.add(str.to_s) + end + + protected var closed = false + redef fun close do closed = true +end + +# Stream from a String. +# +# Mainly used for compatibility with IStream type and tests. +class StringIStream + super IStream + + # The string to read from. + var source: String + + # The current position in the string. + private var cursor: Int = 0 + + redef fun read_char do + if cursor < source.length then + var c = source[cursor].ascii + + cursor += 1 + return c + else + return -1 + end + end + + redef fun close do + source = "" + end + + redef fun eof do return cursor >= source.length end