1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
11 # Input and output streams of characters
23 # Any kind of error that could be produced by an operation on Streams
28 # Abstract stream class
30 # Error produced by the file stream
32 # var ifs = new IFStream.open("donotmakethisfile.binx")
35 # assert ifs.last_error != null
36 var last_error
: nullable IOError = null
42 # Abstract input streams
43 abstract class IStream
45 # Read a character. Return its ASCII value, -1 on EOF or timeout
46 fun read_char
: Int is abstract
48 # Read at most i bytes
49 fun read
(i
: Int): String
51 if last_error
!= null then return ""
52 var s
= new FlatBuffer.with_capacity
(i
)
53 while i
> 0 and not eof
do
63 # Read a string until the end of the line.
66 if last_error
!= null then return ""
68 var s
= new FlatBuffer
73 # Read all the stream until the eof.
76 if last_error
!= null then return ""
77 var s
= new FlatBuffer
80 if c
>= 0 then s
.add
(c
.ascii
)
85 # Read a string until the end of the line and append it to `s`.
86 fun append_line_to
(s
: Buffer)
88 if last_error
!= null then return
96 if c
== '\n' then return
101 # Is there something to read.
102 # This function returns 'false' if there is something to read.
103 fun eof
: Bool is abstract
106 # IStream capable of declaring if readable without blocking
107 abstract class PollableIStream
110 # Is there something to read? (without blocking)
111 fun poll_in
: Bool is abstract
115 # Abstract output stream
116 abstract class OStream
119 fun write
(s
: Text) is abstract
121 # Can the stream be used to write
122 fun is_writable
: Bool is abstract
125 # Things that can be efficienlty writen to a OStream
127 # The point of this interface it to allow is instance to be efficenty
128 # writen into a OStream without having to allocate a big String object
130 # ready-to-save documents usually provide this interface.
132 # Write itself to a `stream`
133 # The specific logic it let to the concrete subclasses
134 fun write_to
(stream
: OStream) is abstract
136 # Like `write_to` but return a new String (may be quite large)
138 # This funtionnality is anectodical, since the point
139 # of streamable object to to be efficienlty written to a
140 # stream without having to allocate and concatenate strings
141 fun write_to_string
: String
143 var stream
= new StringOStream
151 redef fun write_to
(stream
) do stream
.write
(self)
154 # Input streams with a buffer
155 abstract class BufferedIStream
159 if last_error
!= null then return 0
160 if eof
then last_error
= new IOError("Stream has reached eof")
161 if _buffer_pos
>= _buffer
.length
then
164 if _buffer_pos
>= _buffer
.length
then
167 var c
= _buffer
.chars
[_buffer_pos
]
174 if last_error
!= null then return ""
175 if _buffer
.length
== _buffer_pos
then
182 if _buffer_pos
+ i
>= _buffer
.length
then
183 var from
= _buffer_pos
184 _buffer_pos
= _buffer
.length
185 return _buffer
.substring_from
(from
).to_s
188 return _buffer
.substring
(_buffer_pos
- i
, i
).to_s
193 if last_error
!= null then return ""
194 var s
= new FlatBuffer
197 var k
= _buffer
.length
208 redef fun append_line_to
(s
)
211 # First phase: look for a '\n'
213 while i
< _buffer
.length
and _buffer
.chars
[i
] != '\n' do i
+= 1
215 # if there is something to append
216 if i
> _buffer_pos
then
217 # Enlarge the string (if needed)
218 s
.enlarge
(s
.length
+ i
- _buffer_pos
)
220 # Copy from the buffer to the string
223 s
.add
(_buffer
.chars
[j
])
228 if i
< _buffer
.length
then
229 # so \n is in _buffer[i]
230 _buffer_pos
= i
+ 1 # skip \n
244 redef fun eof
do return _buffer_pos
>= _buffer
.length
and end_reached
247 private var buffer
: nullable FlatBuffer = null
249 # The current position in the buffer
250 private var buffer_pos
: Int = 0
253 protected fun fill_buffer
is abstract
255 # Is the last fill_buffer reach the end
256 protected fun end_reached
: Bool is abstract
258 # Allocate a `_buffer` for a given `capacity`.
259 protected fun prepare_buffer
(capacity
: Int)
261 _buffer
= new FlatBuffer.with_capacity
(capacity
)
262 _buffer_pos
= 0 # need to read
266 abstract class IOStream
271 # Stream to a String.
273 # Mainly used for compatibility with OStream type and tests.
277 private var content
= new Array[String]
278 redef fun to_s
do return content
.to_s
279 redef fun is_writable
do return not closed
283 content
.add
(str
.to_s
)
286 protected var closed
= false
287 redef fun close
do closed
= true
290 # Stream from a String.
292 # Mainly used for compatibility with IStream type and tests.
296 # The string to read from.
299 # The current position in the string.
300 private var cursor
: Int = 0
302 redef fun read_char
do
303 if cursor
< source
.length
then
304 var c
= source
[cursor
].ascii
317 redef fun eof
do return cursor
>= source
.length