1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
5 # This file is free software, which comes along with NIT. This software is
6 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 # is kept unaltered, and a notification of the changes is added.
10 # You are allowed to redistribute it and sell it, alone or is a part of
13 # This module handle abstract input and output streams
18 # Abstract stream class
24 # Abstract input streams
27 # Read a character. Return its ASCII value, -1 on EOF or timeout
28 fun read_char
: Int is abstract
30 # Read at most i bytes
31 fun read
(i
: Int): String
33 var s
= new Buffer.with_capacity
(i
)
34 while i
> 0 and not eof
do
44 # Read a string until the end of the line.
53 # Read all the stream until the eof.
59 if c
>= 0 then s
.add
(c
.ascii
)
64 # Read a string until the end of the line and append it to `s'.
65 fun append_line_to
(s
: Buffer)
74 if c
== '\n' then return
79 # Is there something to read.
80 fun eof
: Bool is abstract
83 # Abstract output stream
87 fun write
(s
: String) is abstract
89 # Can the stream be used to write
90 fun is_writable
: Bool is abstract
93 # Input streams with a buffer
99 if _buffer_pos
>= _buffer
.length
then
102 if _buffer_pos
>= _buffer
.length
then
105 var c
= _buffer
[_buffer_pos
]
112 var s
= new Buffer.with_capacity
(i
)
114 var k
= _buffer
.length
118 if eof
then return s
.to_s
122 while j
< k
and i
> 0 do
137 var k
= _buffer
.length
148 redef fun append_line_to
(s
)
151 # First phase: look for a '\n'
153 while i
< _buffer
.length
and _buffer
[i
] != '\n' do i
+= 1
155 # if there is something to append
156 if i
> _buffer_pos
then
157 # Enlarge the string (if needed)
158 s
.enlarge
(s
.length
+ i
- _buffer_pos
)
160 # Copy from the buffer to the string
168 if i
< _buffer
.length
then
169 # so \n is in _buffer[i]
170 _buffer_pos
= i
+ 1 # skip \n
184 redef fun eof
do return _buffer_pos
>= _buffer
.length
and end_reached
187 var _buffer
: nullable Buffer = null
189 # The current position in the buffer
190 var _buffer_pos
: Int = 0
193 protected fun fill_buffer
is abstract
195 # Is the last fill_buffer reach the end
196 protected fun end_reached
: Bool is abstract
198 # Allocate a `_buffer' for a given `capacity'.
199 protected fun prepare_buffer
(capacity
: Int)
201 _buffer
= new Buffer.with_capacity
(capacity
)
202 _buffer_pos
= 0 # need to read
211 ##############################################################"
218 redef fun close
do native_close
(_fd
)
220 private fun native_close
(i
: Int): Int is extern "stream_FDStream_FDStream_native_close_1"
221 private fun native_read_char
(i
: Int): Int is extern "stream_FDStream_FDStream_native_read_char_1"
222 private fun native_read
(i
: Int, buf
: NativeString, len
: Int): Int is extern "stream_FDStream_FDStream_native_read_3"
223 private fun native_write
(i
: Int, buf
: NativeString, len
: Int): Int is extern "stream_FDStream_FDStream_native_write_3"
225 init(fd
: Int) do _fd
= fd
231 redef readable var _eof
: Bool = false
235 var nb
= native_read_char
(_fd
)
236 if nb
== -1 then _eof
= true
246 redef readable var _is_writable
: Bool
250 var nb
= native_write
(_fd
, s
.to_cstring
, s
.length
)
251 if nb
< s
.length
then _is_writable
= false