1 ! Copyright (C) 2005, 2010 Slava Pestov, Doug Coleman
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: math kernel io sequences io.buffers io.timeouts generic
4 byte-vectors system io.encodings math.order io.backend
5 continuations classes byte-arrays namespaces splitting grouping
6 dlists alien alien.c-types alien.data assocs io.encodings.binary
7 summary accessors destructors combinators fry specialized-arrays
9 SPECIALIZED-ARRAY: uchar
12 SYMBOL: default-buffer-size
13 64 1024 * default-buffer-size set-global
15 TUPLE: port < disposable handle timeout ;
17 M: port timeout timeout>> ;
19 M: port set-timeout timeout<< ;
21 : <port> ( handle class -- port )
22 new-disposable swap >>handle ; inline
24 TUPLE: buffered-port < port { buffer buffer } ;
26 : <buffered-port> ( handle class -- port )
28 default-buffer-size get <buffer> >>buffer ; inline
30 TUPLE: input-port < buffered-port ;
32 M: input-port stream-element-type drop +byte+ ; inline
34 : <input-port> ( handle -- input-port )
35 input-port <buffered-port> ;
37 HOOK: (wait-to-read) io-backend ( port -- )
39 : wait-to-read ( port -- eof? )
40 dup buffer>> buffer-empty? [
41 dup (wait-to-read) buffer>> buffer-empty?
42 ] [ drop f ] if ; inline
44 M: input-port stream-read1
46 dup wait-to-read [ drop f ] [ buffer>> buffer-pop ] if ; inline
48 : read-step ( count port -- byte-array/f )
50 { [ over 0 = ] [ 2drop f ] }
51 { [ dup wait-to-read ] [ 2drop f ] }
52 [ buffer>> buffer-read ]
55 : prepare-read ( count stream -- count stream )
56 dup check-disposed [ 0 max >fixnum ] dip ; inline
58 M: input-port stream-read-partial ( max stream -- byte-array/f )
59 prepare-read read-step ;
61 : read-loop ( count port accum -- )
62 pick over length - dup 0 > [
72 M: input-port stream-read
83 : read-until-step ( separators port -- string/f separator/f )
84 dup wait-to-read [ 2drop f f ] [ buffer>> buffer-until ] if ;
86 : read-until-loop ( seps port buf -- separator/f )
87 2over read-until-step over [
97 M: input-port stream-read-until ( seps port -- str/f sep/f )
98 2dup read-until-step dup [ [ 2drop ] 2dip ] [
101 BV{ } like [ read-until-loop ] keep B{ } like swap
102 ] [ [ 2drop ] 2dip ] if
105 TUPLE: output-port < buffered-port ;
107 : <output-port> ( handle -- output-port )
108 output-port <buffered-port> ;
110 : wait-to-write ( len port -- )
111 [ nip ] [ buffer>> buffer-capacity <= ] 2bi
112 [ drop ] [ stream-flush ] if ; inline
114 M: output-port stream-element-type
115 stream>> stream-element-type ; inline
117 M: output-port stream-write1
120 buffer>> byte>buffer ; inline
122 : write-in-groups ( byte-array port -- )
123 [ binary-object uchar <c-direct-array> ] dip
124 [ buffer>> size>> <sliced-groups> ] [ '[ _ stream-write ] ] bi
127 M: output-port stream-write
129 2dup [ byte-length ] [ buffer>> size>> ] bi* > [
132 [ [ byte-length ] dip wait-to-write ]
133 [ buffer>> >buffer ] 2bi
136 HOOK: (wait-to-write) io-backend ( port -- )
138 : port-flush ( port -- )
139 dup buffer>> buffer-empty?
140 [ drop ] [ dup (wait-to-write) port-flush ] if ;
142 M: output-port stream-flush ( port -- )
143 [ check-disposed ] [ port-flush ] bi ;
145 HOOK: tell-handle os ( handle -- n )
147 HOOK: seek-handle os ( n seek-type handle -- )
149 M: input-port stream-tell ( stream -- n )
151 [ [ handle>> tell-handle ] [ buffer>> buffer-length ] bi - ] bi ;
153 M: output-port stream-tell ( stream -- n )
155 [ [ handle>> tell-handle ] [ buffer>> buffer-length ] bi + ] bi ;
157 :: do-seek-relative ( n seek-type stream -- n seek-type stream )
158 ! seek-relative needs special handling here, because of the
160 seek-type seek-relative eq?
161 [ n stream stream-tell + seek-absolute ] [ n seek-type ] if
164 M: input-port stream-seek ( n seek-type stream -- )
167 [ buffer>> 0 swap buffer-reset ]
168 [ handle>> seek-handle ] tri ;
170 M: output-port stream-seek ( n seek-type stream -- )
174 [ handle>> seek-handle ] tri ;
176 GENERIC: shutdown ( handle -- )
178 M: object shutdown drop ;
180 M: output-port dispose*
183 [ handle>> &dispose drop ]
184 [ buffer>> &dispose drop ]
186 [ handle>> shutdown ]
190 M: buffered-port dispose*
191 [ call-next-method ] [ buffer>> dispose ] bi ;
193 M: port cancel-operation handle>> cancel-operation ;
197 [ handle>> &dispose drop ]
198 [ handle>> shutdown ]
202 GENERIC: underlying-port ( stream -- port )
204 M: port underlying-port ;
206 M: encoder underlying-port stream>> underlying-port ;
208 M: decoder underlying-port stream>> underlying-port ;
210 GENERIC: underlying-handle ( stream -- handle )
212 M: object underlying-handle underlying-port handle>> ;
214 ! Fast-path optimization
215 USING: hints strings io.encodings.utf8 io.encodings.ascii
216 io.encodings.private ;
218 HINTS: decoder-read-until { string input-port utf8 } { string input-port ascii } ;
220 HINTS: decoder-readln { input-port utf8 } { input-port ascii } ;