2005-03-29 19:58:22 -05:00
|
|
|
! Copyright (C) 2005 Slava Pestov.
|
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
|
|
|
IN: io-internals
|
2005-04-03 19:02:50 -04:00
|
|
|
USING: errors generic kernel math sequences strings ;
|
2005-03-29 19:58:22 -05:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
TUPLE: port handle buffer error ;
|
2005-04-03 18:28:55 -04:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
C: port ( handle buffer -- port )
|
|
|
|
[ set-delegate ] keep [ set-port-handle ] keep ;
|
2005-04-03 18:28:55 -04:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
: buffered-port 8192 <port> ;
|
|
|
|
: >port< dup port-handle swap delegate ;
|
2005-04-03 18:28:55 -04:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
TUPLE: reader line ready? ;
|
|
|
|
|
|
|
|
C: reader ( handle -- reader )
|
|
|
|
[ >r buffered-port r> set-delegate ] keep ;
|
|
|
|
|
|
|
|
: pending-error ( reader -- ) port-error throw ;
|
2005-04-03 16:55:56 -04:00
|
|
|
|
2005-04-03 18:28:55 -04:00
|
|
|
: read-line-loop ( line buffer -- ? )
|
2005-04-03 16:55:56 -04:00
|
|
|
dup buffer-length 0 = [
|
|
|
|
2drop f
|
|
|
|
] [
|
2005-04-05 22:18:36 -04:00
|
|
|
dup buffer-pop dup CHAR: \n = [
|
2005-04-03 16:55:56 -04:00
|
|
|
3drop t
|
|
|
|
] [
|
2005-04-05 22:18:36 -04:00
|
|
|
pick sbuf-append read-line-loop
|
2005-04-03 16:55:56 -04:00
|
|
|
] ifte
|
|
|
|
] ifte ;
|
|
|
|
|
2005-04-03 19:02:50 -04:00
|
|
|
: read-line-step ( reader -- ? )
|
2005-04-07 20:02:59 -04:00
|
|
|
[ dup reader-line swap read-line-loop dup ] keep
|
|
|
|
set-reader-ready? ;
|
2005-04-03 16:55:56 -04:00
|
|
|
|
2005-04-03 18:28:55 -04:00
|
|
|
: init-reader ( count reader -- ) >r <sbuf> r> set-reader-line ;
|
2005-04-03 16:55:56 -04:00
|
|
|
|
|
|
|
: prepare-line ( reader -- ? )
|
2005-04-03 19:02:50 -04:00
|
|
|
80 over init-reader read-line-step ;
|
2005-04-03 16:55:56 -04:00
|
|
|
|
|
|
|
: can-read-line? ( reader -- ? )
|
2005-04-03 18:28:55 -04:00
|
|
|
dup pending-error
|
2005-04-03 16:55:56 -04:00
|
|
|
dup reader-ready? [ drop t ] [ prepare-line ] ifte ;
|
|
|
|
|
|
|
|
: reader-eof ( reader -- )
|
|
|
|
dup reader-line dup [
|
2005-04-03 18:28:55 -04:00
|
|
|
length 0 = [ f over set-reader-line ] when
|
2005-04-03 16:55:56 -04:00
|
|
|
] [
|
|
|
|
drop
|
|
|
|
] ifte t swap set-reader-ready? ;
|
2005-04-03 18:28:55 -04:00
|
|
|
|
|
|
|
GENERIC: refill* ( reader -- )
|
|
|
|
|
|
|
|
: refill ( reader -- )
|
2005-04-07 20:02:59 -04:00
|
|
|
dup buffer-length 0 = [ refill* ] [ drop ] ifte ;
|
2005-04-03 18:28:55 -04:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
: reader-eof? ( reader -- ? ) buffer-fill 0 = ;
|
2005-04-03 18:28:55 -04:00
|
|
|
|
|
|
|
: read-line-task ( reader -- ? )
|
|
|
|
dup refill dup reader-eof? [
|
|
|
|
reader-eof t
|
|
|
|
] [
|
|
|
|
read-line-step
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: read-count-step ( count reader -- ? )
|
2005-04-07 20:02:59 -04:00
|
|
|
dup reader-line -rot >r over length - r>
|
|
|
|
2dup buffer-fill <= [
|
2005-04-03 18:28:55 -04:00
|
|
|
buffer> swap sbuf-append t
|
|
|
|
] [
|
|
|
|
buffer>> nip swap sbuf-append f
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: can-read-count? ( count reader -- ? )
|
|
|
|
dup pending-error
|
|
|
|
2dup reader-line length >= [
|
|
|
|
2drop t
|
|
|
|
] [
|
|
|
|
2dup init-reader read-count-step
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: read-count-task ( count reader -- ? )
|
|
|
|
dup refill dup reader-eof? [
|
|
|
|
nip reader-eof t
|
|
|
|
] [
|
|
|
|
read-count-step
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: pop-line ( reader -- str )
|
2005-04-05 22:18:36 -04:00
|
|
|
dup reader-line dup [ sbuf>string ] when >r
|
2005-04-03 18:28:55 -04:00
|
|
|
f over set-reader-line
|
|
|
|
f swap set-reader-ready? r> ;
|
|
|
|
|
|
|
|
: read-fin ( reader -- str )
|
|
|
|
dup pending-error dup reader-ready? [
|
|
|
|
pop-line
|
|
|
|
] [
|
|
|
|
"reader not ready" throw
|
|
|
|
] ifte ;
|
2005-04-03 19:02:50 -04:00
|
|
|
|
|
|
|
: file-mode OCT: 0600 ;
|
|
|
|
|
|
|
|
: io-error ( n -- ) 0 < [ errno strerror throw ] when ;
|
|
|
|
|
|
|
|
: open-read ( path -- fd )
|
|
|
|
O_RDONLY file-mode sys-open dup io-error ;
|
|
|
|
|
|
|
|
: open-write ( path -- fd )
|
|
|
|
O_WRONLY O_CREAT bitor O_TRUNC bitor file-mode sys-open
|
|
|
|
dup io-error ;
|
|
|
|
|
|
|
|
: read-step ( fd buffer -- ? )
|
|
|
|
tuck dup buffer-end swap buffer-capacity sys-read
|
|
|
|
dup 0 >= [ swap n>buffer t ] [ 2drop f ] ifte ;
|
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
M: reader refill* ( reader -- )
|
|
|
|
>port< read-step drop ;
|
|
|
|
|
|
|
|
: write-step ( fd buffer -- ? )
|
|
|
|
tuck dup buffer@ swap buffer-length sys-write
|
|
|
|
dup 0 >= [ buffer-consume t ] [ drop f ] ifte ;
|
2005-04-03 19:02:50 -04:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
: can-write? ( len writer -- ? )
|
|
|
|
#! If the buffer is empty and the string is too long,
|
|
|
|
#! extend the buffer.
|
|
|
|
dup pending-error
|
|
|
|
dup buffer-fill 0 = >r 2dup buffer-capacity > r> and [
|
|
|
|
buffer-extend t
|
|
|
|
] [
|
|
|
|
[ buffer-fill + ] keep buffer-capacity <=
|
|
|
|
] ifte ;
|
2005-04-03 19:02:50 -04:00
|
|
|
|
2005-04-07 20:02:59 -04:00
|
|
|
: write-task ( writer -- ? )
|
|
|
|
dup buffer-length 0 = over port-error or [
|
|
|
|
buffer-reset t
|
|
|
|
] [
|
|
|
|
>port< write-step
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: write-fin ( str writer -- )
|
|
|
|
dup pending-error
|
|
|
|
>r dup string? [ ch>string ] unless r> >buffer ;
|