X-Git-Url: http://nitlanguage.org?ds=sidebyside diff --git a/lib/standard/stream.nit b/lib/standard/stream.nit index d26d95f..a94601c 100644 --- a/lib/standard/stream.nit +++ b/lib/standard/stream.nit @@ -13,13 +13,14 @@ # Input and output streams of characters module stream -import string +intrude import ropes in "C" `{ #include #include #include #include + #include `} # Abstract stream class @@ -88,16 +89,77 @@ 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 end +# Things that can be efficienlty writen to a OStream +# +# The point of this interface it to allow is instance to be efficenty +# writen into a OStream without having to allocate a big String object +# +# ready-to-save documents usually provide this interface. +interface Streamable + # Write itself to a `stream` + # The specific logic it let to the concrete subclasses + fun write_to(stream: OStream) is abstract + + # Like `write_to` but return a new String (may be quite large) + # + # This funtionnality is anectodical, since the point + # of streamable object to to be efficienlty written to a + # stream without having to allocate and concatenate strings + fun write_to_string: String + do + var stream = new StringOStream + write_to(stream) + return stream.to_s + end +end + +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 @@ -117,24 +179,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 @@ -361,6 +419,13 @@ class StringOStream 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