1 ! Copyright (C) 2007 Slava Pestov, Doug Coleman
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: math kernel io sequences io.buffers generic sbufs
5 system io.streams.lines io.streams.plain io.streams.duplex
6 continuations debugger classes byte-arrays ;
8 : default-buffer-size 64 1024 * ; inline
10 ! Common delegate of native stream readers and writers
11 TUPLE: port handle error timeout cutoff type eof? ;
17 PREDICATE: port input-port port-type input eq? ;
18 PREDICATE: port output-port port-type output eq? ;
20 GENERIC: init-handle ( handle -- )
22 : <port> ( handle buffer -- port )
31 : <buffered-port> ( handle -- port )
32 default-buffer-size <buffer> <port> ;
34 : <reader> ( handle -- stream )
35 <buffered-port> input over set-port-type <line-reader> ;
37 : <writer> ( handle -- stream )
38 <buffered-port> output over set-port-type <plain-writer> ;
40 : handle>duplex-stream ( in-handle out-handle -- stream )
42 [ >r <reader> r> <duplex-stream> ]
46 : touch-port ( port -- )
47 dup port-timeout dup zero?
48 [ 2drop ] [ millis + swap set-port-cutoff ] if ;
50 : timeout? ( port -- ? )
51 port-cutoff dup zero? not swap millis < and ;
53 : pending-error ( port -- )
54 dup port-error f rot set-port-error [ throw ] when* ;
57 [ set-port-timeout ] keep touch-port ;
59 GENERIC: (wait-to-read) ( port -- )
61 : wait-to-read ( count port -- )
62 tuck buffer-length > [ (wait-to-read) ] [ drop ] if ;
64 : wait-to-read1 ( port -- )
67 : unless-eof ( port quot -- value )
68 >r dup buffer-empty? over port-eof? and
69 [ f swap set-port-eof? f ] r> if ; inline
71 M: input-port stream-read1
72 dup wait-to-read1 [ buffer-pop ] unless-eof ;
74 : read-step ( count port -- string/f )
75 [ wait-to-read ] 2keep
76 [ dupd buffer> ] unless-eof nip ;
78 : read-loop ( count port sbuf -- )
79 pick over length - dup 0 > [
81 over push-all read-loop
89 M: input-port stream-read
104 : read-until-step ( separators port -- string/f separator/f )
107 f swap set-port-eof? drop f f
112 : read-until-loop ( seps port sbuf -- separator/f )
113 pick pick read-until-step over [
114 >r over push-all r> dup [
123 M: input-port stream-read-until ( seps port -- str/f sep/f )
124 2dup read-until-step dup [
128 drop >sbuf [ read-until-loop ] keep "" like swap
134 M: input-port stream-read-partial ( max stream -- string/f )
135 >r 0 max >fixnum r> read-step ;
137 : can-write? ( len writer -- ? )
141 [ buffer-fill + ] keep buffer-capacity <=
144 : wait-to-write ( len port -- )
145 tuck can-write? [ drop ] [ stream-flush ] if ;
147 M: output-port stream-write1
148 1 over wait-to-write ch>buffer ;
150 M: output-port stream-write
151 over length over wait-to-write >buffer ;
153 TUPLE: server-port addr client ;
155 : <server-port> ( port addr -- server )
156 server-port pick set-port-type
157 { set-delegate set-server-port-addr }
158 server-port construct ;
160 : check-server-port ( port -- )
161 port-type server-port assert= ;
163 TUPLE: datagram-port addr packet packet-addr ;
165 : <datagram-port> ( port addr -- datagram )
166 datagram-port pick set-port-type
167 { set-delegate set-datagram-port-addr }
168 datagram-port construct ;
170 : check-datagram-port ( port -- )
171 port-type datagram-port assert= ;
173 : check-datagram-send ( packet addrspec port -- )
174 dup check-datagram-port
175 datagram-port-addr [ class ] 2apply assert=
176 class byte-array assert= ;