2010-02-24 02:18:41 -05:00
|
|
|
! Copyright (C) 2005, 2010 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
|
2008-05-05 03:19:25 -04:00
|
|
|
byte-vectors system io.encodings math.order io.backend
|
2010-02-24 02:18:41 -05:00
|
|
|
continuations classes byte-arrays namespaces splitting grouping
|
|
|
|
dlists alien alien.c-types assocs io.encodings.binary summary
|
2010-07-07 17:32:30 -04:00
|
|
|
accessors destructors combinators fry specialized-arrays
|
|
|
|
locals ;
|
2010-02-24 02:18:41 -05:00
|
|
|
SPECIALIZED-ARRAY: uchar
|
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
|
|
|
|
2009-08-24 03:26:13 -04:00
|
|
|
TUPLE: port < disposable handle timeout ;
|
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
|
|
|
|
2010-05-05 16:52:54 -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 )
|
2009-08-24 03:26:13 -04:00
|
|
|
new-disposable 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-01-31 01:52:06 -05:00
|
|
|
|
2008-05-13 19:24:46 -04:00
|
|
|
: <buffered-port> ( handle class -- port )
|
|
|
|
<port>
|
|
|
|
default-buffer-size get <buffer> >>buffer ; inline
|
2008-01-31 01:52:06 -05:00
|
|
|
|
2008-05-18 20:02:50 -04:00
|
|
|
TUPLE: input-port < buffered-port ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2009-12-13 03:03:06 -05:00
|
|
|
M: input-port stream-element-type drop +byte+ ; inline
|
2009-03-15 18:11:18 -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
|
|
|
|
2010-10-06 11:16:01 -04:00
|
|
|
M: input-port stream-peek1
|
|
|
|
dup check-disposed dup wait-to-read
|
|
|
|
[ drop f ] [ buffer>> buffer-peek1 ] 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-11-06 14:13:37 -05:00
|
|
|
dup wait-to-read [ drop f ] [ buffer>> buffer-pop ] if ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-03-06 16:58:05 -05:00
|
|
|
: read-step ( count port -- byte-array/f )
|
2010-07-30 15:58:33 -04:00
|
|
|
{
|
|
|
|
{ [ over 0 = ] [ 2drop f ] }
|
|
|
|
{ [ dup wait-to-read ] [ 2drop f ] }
|
|
|
|
[ buffer>> buffer-read ]
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: prepare-read ( count stream -- count stream )
|
|
|
|
dup check-disposed [ 0 max >fixnum ] dip ; inline
|
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 )
|
2010-07-30 15:58:33 -04:00
|
|
|
prepare-read read-step ;
|
2008-05-13 19:24:46 -04:00
|
|
|
|
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 [
|
2009-10-28 16:29:01 -04:00
|
|
|
append! read-loop
|
2007-09-20 18:09:08 -04:00
|
|
|
] [
|
|
|
|
2drop 2drop
|
|
|
|
] if
|
|
|
|
] [
|
|
|
|
2drop 2drop
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
M: input-port stream-read
|
2010-07-30 15:58:33 -04:00
|
|
|
prepare-read
|
2007-09-20 18:09:08 -04:00
|
|
|
2dup read-step dup [
|
|
|
|
pick over length > [
|
2008-03-06 16:58:05 -05:00
|
|
|
pick <byte-vector>
|
2007-09-20 18:09:08 -04:00
|
|
|
[ push-all ] keep
|
|
|
|
[ read-loop ] keep
|
2008-03-06 16:58:05 -05:00
|
|
|
B{ } like
|
2008-04-11 15:09:09 -04:00
|
|
|
] [ 2nip ] if
|
|
|
|
] [ 2nip ] if ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-06-12 04:49:59 -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 [
|
2009-10-28 16:29:01 -04:00
|
|
|
[ append! ] dip dup [
|
2008-11-30 14:46:39 -05:00
|
|
|
[ 3drop ] dip
|
2008-06-12 04:49:59 -04:00
|
|
|
] [
|
|
|
|
drop read-until-loop
|
|
|
|
] if
|
|
|
|
] [
|
2008-11-30 14:46:39 -05:00
|
|
|
[ 2drop 2drop ] dip
|
2008-06-12 04:49:59 -04:00
|
|
|
] if ;
|
|
|
|
|
|
|
|
M: input-port stream-read-until ( seps port -- str/f sep/f )
|
2008-11-30 14:46:39 -05:00
|
|
|
2dup read-until-step dup [ [ 2drop ] 2dip ] [
|
2008-06-12 04:49:59 -04:00
|
|
|
over [
|
|
|
|
drop
|
|
|
|
BV{ } like [ read-until-loop ] keep B{ } like swap
|
2008-11-30 14:46:39 -05:00
|
|
|
] [ [ 2drop ] 2dip ] if
|
2008-06-12 04:49:59 -04:00
|
|
|
] 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 -- )
|
2009-01-23 19:20:47 -05:00
|
|
|
[ nip ] [ buffer>> buffer-capacity <= ] 2bi
|
2008-11-06 01:02:44 -05:00
|
|
|
[ drop ] [ stream-flush ] if ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2010-07-07 02:26:03 -04:00
|
|
|
M: output-port stream-element-type
|
|
|
|
stream>> stream-element-type ; inline
|
2009-03-15 18:11:18 -04:00
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
M: output-port stream-write1
|
2008-05-15 00:23:12 -04:00
|
|
|
dup check-disposed
|
2008-04-11 15:09:09 -04:00
|
|
|
1 over wait-to-write
|
2008-11-06 14:13:37 -05:00
|
|
|
buffer>> byte>buffer ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2010-02-24 02:18:41 -05:00
|
|
|
: write-in-groups ( byte-array port -- )
|
|
|
|
[ binary-object <direct-uchar-array> ] dip
|
2010-04-19 02:13:21 -04:00
|
|
|
[ buffer>> size>> <sliced-groups> ] [ '[ _ stream-write ] ] bi
|
2010-02-24 02:18:41 -05:00
|
|
|
each ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
M: output-port stream-write
|
2008-05-15 00:23:12 -04:00
|
|
|
dup check-disposed
|
2010-02-24 02:18:41 -05:00
|
|
|
2dup [ byte-length ] [ buffer>> size>> ] bi* > [
|
|
|
|
write-in-groups
|
2007-11-09 03:01:45 -05:00
|
|
|
] [
|
2010-02-24 02:18:41 -05:00
|
|
|
[ [ byte-length ] dip wait-to-write ]
|
2008-04-11 15:09:09 -04:00
|
|
|
[ 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 -- )
|
|
|
|
|
2010-07-07 02:26:03 -04:00
|
|
|
: port-flush ( port -- )
|
|
|
|
dup buffer>> buffer-empty?
|
|
|
|
[ drop ] [ dup (wait-to-write) port-flush ] if ;
|
|
|
|
|
|
|
|
M: output-port stream-flush ( port -- )
|
|
|
|
[ check-disposed ] [ port-flush ] bi ;
|
|
|
|
|
2009-10-03 19:27:09 -04:00
|
|
|
HOOK: tell-handle os ( handle -- n )
|
2010-07-07 02:26:03 -04:00
|
|
|
|
2009-02-08 11:35:30 -05:00
|
|
|
HOOK: seek-handle os ( n seek-type handle -- )
|
2009-02-07 11:30:51 -05:00
|
|
|
|
2010-07-07 02:26:03 -04:00
|
|
|
M: input-port stream-tell ( stream -- n )
|
2009-10-03 19:27:09 -04:00
|
|
|
[ check-disposed ]
|
2010-07-07 02:26:03 -04:00
|
|
|
[ [ handle>> tell-handle ] [ buffer>> buffer-length ] bi - ] bi ;
|
|
|
|
|
|
|
|
M: output-port stream-tell ( stream -- n )
|
|
|
|
[ check-disposed ]
|
|
|
|
[ [ handle>> tell-handle ] [ buffer>> buffer-length ] bi + ] bi ;
|
2009-10-03 19:27:09 -04:00
|
|
|
|
2010-07-07 17:32:30 -04:00
|
|
|
:: do-seek-relative ( n seek-type stream -- n seek-type stream )
|
|
|
|
! seek-relative needs special handling here, because of the
|
|
|
|
! buffer.
|
|
|
|
seek-type seek-relative eq?
|
|
|
|
[ n stream stream-tell + seek-absolute ] [ n seek-type ] if
|
|
|
|
stream ;
|
|
|
|
|
2009-02-08 11:35:30 -05:00
|
|
|
M: input-port stream-seek ( n seek-type stream -- )
|
2010-07-07 17:32:30 -04:00
|
|
|
do-seek-relative
|
2009-02-08 11:35:30 -05:00
|
|
|
[ check-disposed ]
|
|
|
|
[ buffer>> 0 swap buffer-reset ]
|
|
|
|
[ handle>> seek-handle ] tri ;
|
2009-02-07 11:30:51 -05:00
|
|
|
|
2009-02-08 11:35:30 -05:00
|
|
|
M: output-port stream-seek ( n seek-type stream -- )
|
2010-07-07 17:32:30 -04:00
|
|
|
do-seek-relative
|
2009-02-08 11:35:30 -05:00
|
|
|
[ check-disposed ]
|
|
|
|
[ stream-flush ]
|
|
|
|
[ handle>> seek-handle ] tri ;
|
2009-02-07 11:30:51 -05:00
|
|
|
|
2008-05-21 02:36:30 -04:00
|
|
|
GENERIC: shutdown ( handle -- )
|
|
|
|
|
|
|
|
M: object shutdown drop ;
|
2007-11-07 14:01:45 -05:00
|
|
|
|
2008-05-18 18:18:28 -04:00
|
|
|
M: output-port dispose*
|
2008-05-20 22:59:29 -04:00
|
|
|
[
|
2008-08-15 17:13:13 -04:00
|
|
|
{
|
|
|
|
[ handle>> &dispose drop ]
|
2008-08-15 19:57:00 -04:00
|
|
|
[ buffer>> &dispose drop ]
|
2008-08-15 17:13:13 -04:00
|
|
|
[ port-flush ]
|
|
|
|
[ handle>> shutdown ]
|
|
|
|
} cleave
|
2008-05-20 22:59:29 -04:00
|
|
|
] 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
|
|
|
|
2008-05-21 02:36:30 -04:00
|
|
|
M: port cancel-operation handle>> cancel-operation ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-05-21 02:36:30 -04:00
|
|
|
M: port dispose*
|
|
|
|
[
|
|
|
|
[ handle>> &dispose drop ]
|
2008-05-21 16:54:27 -04:00
|
|
|
[ handle>> shutdown ]
|
2008-05-21 02:36:30 -04:00
|
|
|
bi
|
|
|
|
] with-destructors ;
|
2008-07-12 02:08:30 -04:00
|
|
|
|
2008-11-30 14:46:39 -05:00
|
|
|
GENERIC: underlying-port ( stream -- port )
|
|
|
|
|
|
|
|
M: port underlying-port ;
|
|
|
|
|
|
|
|
M: encoder underlying-port stream>> underlying-port ;
|
|
|
|
|
|
|
|
M: decoder underlying-port stream>> underlying-port ;
|
|
|
|
|
|
|
|
GENERIC: underlying-handle ( stream -- handle )
|
|
|
|
|
|
|
|
M: object underlying-handle underlying-port handle>> ;
|
|
|
|
|
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 } ;
|