factor/basis/io/ports/ports.factor

163 lines
4.1 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2008 Slava Pestov, Doug Coleman
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-02-09 22:34:42 -05:00
USING: math kernel io sequences io.buffers io.timeouts generic
byte-vectors system io.encodings math.order io.backend
continuations debugger classes byte-arrays namespaces splitting
2008-07-02 01:20:01 -04:00
grouping dlists assocs io.encodings.binary summary accessors
destructors ;
2008-05-13 19:24:46 -04:00
IN: io.ports
2007-09-20 18:09:08 -04:00
2007-11-07 14:01:45 -05:00
SYMBOL: default-buffer-size
64 1024 * default-buffer-size set-global
2007-09-20 18:09:08 -04:00
2008-05-18 00:50:11 -04:00
TUPLE: port handle timeout disposed ;
2008-02-21 20:12:55 -05:00
2008-04-11 17:08:40 -04:00
M: port timeout timeout>> ;
2008-02-09 22:34:42 -05:00
2008-04-11 17:08:40 -04:00
M: port set-timeout (>>timeout) ;
2007-09-20 18:09:08 -04:00
2008-04-11 17:08:40 -04:00
: <port> ( handle class -- port )
2008-05-15 19:14:46 -04:00
new swap >>handle ; inline
2007-09-20 18:09:08 -04:00
2008-07-12 02:08:30 -04:00
TUPLE: buffered-port < port { buffer buffer } ;
2008-05-13 19:24:46 -04:00
: <buffered-port> ( handle class -- port )
<port>
default-buffer-size get <buffer> >>buffer ; inline
2008-05-18 20:02:50 -04:00
TUPLE: input-port < buffered-port ;
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
: <input-port> ( handle -- input-port )
input-port <buffered-port> ;
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
HOOK: (wait-to-read) io-backend ( port -- )
2007-09-20 18:09:08 -04:00
2008-05-18 20:02:50 -04:00
: wait-to-read ( port -- eof? )
dup buffer>> buffer-empty? [
dup (wait-to-read) buffer>> buffer-empty?
2008-07-12 02:08:30 -04:00
] [ drop f ] if ; inline
2007-09-20 18:09:08 -04:00
M: input-port stream-read1
2008-05-15 00:23:12 -04:00
dup check-disposed
2008-05-18 20:02:50 -04:00
dup wait-to-read [ drop f ] [ buffer>> buffer-pop ] if ;
2007-09-20 18:09:08 -04:00
: read-step ( count port -- byte-array/f )
2008-05-18 20:02:50 -04:00
dup wait-to-read [ 2drop f ] [ buffer>> buffer-read ] if ;
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
M: input-port stream-read-partial ( max stream -- byte-array/f )
2008-05-15 00:23:12 -04:00
dup check-disposed
2008-05-13 19:24:46 -04:00
>r 0 max >integer r> read-step ;
2008-03-08 03:51:26 -05:00
: read-loop ( count port accum -- )
2007-09-20 18:09:08 -04:00
pick over length - dup 0 > [
pick read-step dup [
over push-all read-loop
] [
2drop 2drop
] if
] [
2drop 2drop
] if ;
M: input-port stream-read
2008-05-15 00:23:12 -04:00
dup check-disposed
2007-09-20 18:09:08 -04:00
>r 0 max >fixnum r>
2dup read-step dup [
pick over length > [
pick <byte-vector>
2007-09-20 18:09:08 -04:00
[ push-all ] keep
[ read-loop ] keep
B{ } like
] [ 2nip ] if
] [ 2nip ] if ;
2007-09-20 18:09:08 -04:00
: read-until-step ( separators port -- string/f separator/f )
dup wait-to-read [ 2drop f f ] [ buffer>> buffer-until ] if ;
: read-until-loop ( seps port buf -- separator/f )
2over read-until-step over [
>r over push-all r> dup [
>r 3drop r>
] [
drop read-until-loop
] if
] [
>r 2drop 2drop r>
] if ;
M: input-port stream-read-until ( seps port -- str/f sep/f )
2dup read-until-step dup [ >r 2nip r> ] [
over [
drop
BV{ } like [ read-until-loop ] keep B{ } like swap
] [ >r 2nip r> ] if
] if ;
2008-05-13 19:24:46 -04:00
TUPLE: output-port < buffered-port ;
: <output-port> ( handle -- output-port )
output-port <buffered-port> ;
2007-09-20 18:09:08 -04:00
: wait-to-write ( len port -- )
2008-06-14 03:45:04 -04:00
tuck buffer>> buffer-capacity <=
[ drop ] [ stream-flush ] if ;
2007-09-20 18:09:08 -04:00
M: output-port stream-write1
2008-05-15 00:23:12 -04:00
dup check-disposed
1 over wait-to-write
buffer>> byte>buffer ;
2007-09-20 18:09:08 -04:00
M: output-port stream-write
2008-05-15 00:23:12 -04:00
dup check-disposed
over length over buffer>> buffer-size > [
2008-06-29 03:17:32 -04:00
[ buffer>> size>> <groups> ]
[ [ stream-write ] curry ] bi
each
2007-11-09 03:01:45 -05:00
] [
[ >r length r> wait-to-write ]
[ buffer>> >buffer ] 2bi
2007-11-09 03:01:45 -05:00
] if ;
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
HOOK: (wait-to-write) io-backend ( port -- )
GENERIC: shutdown ( handle -- )
M: object shutdown drop ;
2008-05-18 00:50:11 -04:00
: port-flush ( port -- )
dup buffer>> buffer-empty?
[ drop ] [ dup (wait-to-write) port-flush ] if ;
2007-11-07 14:01:45 -05:00
M: output-port stream-flush ( port -- )
2008-05-18 00:50:11 -04:00
[ check-disposed ] [ port-flush ] bi ;
2007-11-07 14:01:45 -05:00
2008-05-18 18:18:28 -04:00
M: output-port dispose*
[
[ handle>> &dispose drop ]
[ port-flush ]
2008-05-21 16:54:27 -04:00
[ handle>> shutdown ]
tri
] with-destructors ;
2008-04-11 17:08:40 -04:00
2008-05-15 00:23:12 -04:00
M: buffered-port dispose*
2008-07-12 02:08:30 -04:00
[ call-next-method ] [ buffer>> dispose ] bi ;
2007-09-20 18:09:08 -04:00
M: port cancel-operation handle>> cancel-operation ;
2007-09-20 18:09:08 -04:00
M: port dispose*
[
[ handle>> &dispose drop ]
2008-05-21 16:54:27 -04:00
[ handle>> shutdown ]
bi
] with-destructors ;
2008-07-12 02:08:30 -04:00
! Fast-path optimization
USING: hints strings io.encodings.utf8 io.encodings.ascii
io.encodings.private ;
HINTS: decoder-read-until { string input-port utf8 } { string input-port ascii } ;
HINTS: decoder-readln { input-port utf8 } { input-port ascii } ;
HINTS: decoder-write { string output-port utf8 } { string output-port ascii } ;