2008-02-21 16:22:49 -05:00
|
|
|
! Copyright (C) 2008 Daniel Ehrenberg.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-02-16 16:35:44 -05:00
|
|
|
USING: math kernel sequences sbufs vectors namespaces
|
2008-02-21 16:22:49 -05:00
|
|
|
growable strings io classes continuations combinators
|
2008-03-14 04:09:51 -04:00
|
|
|
io.styles io.streams.plain splitting
|
|
|
|
io.streams.duplex byte-arrays sequences.private ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: io.encodings
|
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
! The encoding descriptor protocol
|
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
GENERIC: decode-char ( stream encoding -- char/f )
|
2008-03-05 15:51:01 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
GENERIC: encode-char ( char stream encoding -- )
|
2008-03-05 15:51:01 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
GENERIC: <decoder> ( stream decoding -- newstream )
|
2008-03-05 15:51:01 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
GENERIC: <encoder> ( stream encoding -- newstream )
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
: replacement-char HEX: fffd ;
|
2008-02-01 18:45:35 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
! Decoding
|
2008-02-13 02:02:37 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
<PRIVATE
|
2008-02-13 02:02:37 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
TUPLE: decode-error ;
|
2008-02-13 02:02:37 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
: decode-error ( -- * ) \ decode-error construct-empty throw ;
|
2008-02-13 18:53:10 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
TUPLE: decoder stream code cr ;
|
|
|
|
M: tuple-class <decoder> construct-empty <decoder> ;
|
|
|
|
M: tuple <decoder> f decoder construct-boa ;
|
2008-02-11 00:14:42 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
: >decoder< ( decoder -- stream encoding )
|
|
|
|
{ decoder-stream decoder-code } get-slots ;
|
2008-02-11 00:14:42 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
: cr+ t swap set-decoder-cr ; inline
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
: cr- f swap set-decoder-cr ; inline
|
2008-02-16 16:35:44 -05:00
|
|
|
|
|
|
|
: line-ends/eof ( stream str -- str ) f like swap cr- ; inline
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-02-16 16:35:44 -05:00
|
|
|
: line-ends\r ( stream str -- str ) swap cr+ ; inline
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-02-16 16:35:44 -05:00
|
|
|
: line-ends\n ( stream str -- str )
|
2008-03-05 15:51:01 -05:00
|
|
|
over decoder-cr over empty? and
|
2008-02-16 16:35:44 -05:00
|
|
|
[ drop dup cr- stream-readln ] [ swap cr- ] if ; inline
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-02-16 16:35:44 -05:00
|
|
|
: handle-readln ( stream str ch -- str )
|
|
|
|
{
|
|
|
|
{ f [ line-ends/eof ] }
|
|
|
|
{ CHAR: \r [ line-ends\r ] }
|
|
|
|
{ CHAR: \n [ line-ends\n ] }
|
|
|
|
} case ;
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-02-16 16:35:44 -05:00
|
|
|
: fix-read ( stream string -- string )
|
2008-03-05 15:51:01 -05:00
|
|
|
over decoder-cr [
|
2008-02-16 16:35:44 -05:00
|
|
|
over cr-
|
|
|
|
"\n" ?head [
|
2008-03-14 04:09:51 -04:00
|
|
|
over stream-read1 [ add ] when*
|
|
|
|
] when
|
|
|
|
] when nip ;
|
|
|
|
|
|
|
|
: read-loop ( n stream -- string )
|
2008-03-18 17:01:14 -04:00
|
|
|
SBUF" " clone [
|
2008-03-14 04:09:51 -04:00
|
|
|
[
|
2008-03-18 17:01:14 -04:00
|
|
|
>r nip stream-read1 dup
|
|
|
|
[ r> push f ] [ r> 2drop t ] if
|
|
|
|
] 2curry find-integer drop
|
|
|
|
] keep "" like f like ;
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
M: decoder stream-read
|
2008-03-14 04:09:51 -04:00
|
|
|
tuck read-loop fix-read ;
|
2008-02-16 16:35:44 -05:00
|
|
|
|
2008-03-18 17:01:14 -04:00
|
|
|
M: decoder stream-read-partial stream-read ;
|
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
: (read-until) ( buf quot -- string/f sep/f )
|
2008-03-18 17:01:14 -04:00
|
|
|
! quot: -- char stop?
|
2008-03-14 04:09:51 -04:00
|
|
|
dup call
|
|
|
|
[ >r drop "" like r> ]
|
|
|
|
[ pick push (read-until) ] if ; inline
|
2008-02-16 23:17:41 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
M: decoder stream-read-until
|
2008-03-14 04:09:51 -04:00
|
|
|
SBUF" " clone -rot >decoder<
|
2008-03-18 17:01:14 -04:00
|
|
|
[ decode-char [ dup rot memq? ] [ drop f t ] if* ] 3curry
|
|
|
|
(read-until) ;
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-02-16 16:35:44 -05:00
|
|
|
: fix-read1 ( stream char -- char )
|
2008-03-05 15:51:01 -05:00
|
|
|
over decoder-cr [
|
2008-02-16 16:35:44 -05:00
|
|
|
over cr-
|
|
|
|
dup CHAR: \n = [
|
2008-03-14 04:09:51 -04:00
|
|
|
drop dup stream-read1
|
|
|
|
] when
|
|
|
|
] when nip ;
|
2008-02-16 16:35:44 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
M: decoder stream-read1
|
2008-03-14 04:09:51 -04:00
|
|
|
dup >decoder< decode-char fix-read1 ;
|
2008-02-16 16:35:44 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
M: decoder stream-readln ( stream -- str )
|
2008-02-16 16:35:44 -05:00
|
|
|
"\r\n" over stream-read-until handle-readln ;
|
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
M: decoder dispose decoder-stream dispose ;
|
|
|
|
|
2008-02-16 16:35:44 -05:00
|
|
|
! Encoding
|
|
|
|
|
|
|
|
TUPLE: encode-error ;
|
|
|
|
|
|
|
|
: encode-error ( -- * ) \ encode-error construct-empty throw ;
|
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
TUPLE: encoder stream code ;
|
|
|
|
M: tuple-class <encoder> construct-empty <encoder> ;
|
|
|
|
M: tuple <encoder> encoder construct-boa ;
|
|
|
|
|
|
|
|
: >encoder< ( encoder -- stream encoding )
|
|
|
|
{ encoder-stream encoder-code } get-slots ;
|
2008-02-16 16:35:44 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
M: encoder stream-write1
|
2008-03-14 04:09:51 -04:00
|
|
|
>encoder< encode-char ;
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
M: encoder stream-write
|
2008-03-14 04:09:51 -04:00
|
|
|
>encoder< [ encode-char ] 2curry each ;
|
2008-02-16 16:35:44 -05:00
|
|
|
|
2008-03-14 04:09:51 -04:00
|
|
|
M: encoder dispose encoder-stream dispose ;
|
2008-02-13 20:53:53 -05:00
|
|
|
|
2008-03-18 17:01:14 -04:00
|
|
|
M: encoder stream-flush encoder-stream stream-flush ;
|
|
|
|
|
2008-03-05 15:51:01 -05:00
|
|
|
INSTANCE: encoder plain-writer
|
2008-02-15 20:44:35 -05:00
|
|
|
|
2008-02-21 16:22:49 -05:00
|
|
|
! Rebinding duplex streams which have not read anything yet
|
2008-02-15 20:44:35 -05:00
|
|
|
|
2008-02-21 16:22:49 -05:00
|
|
|
: reencode ( stream encoding -- newstream )
|
2008-03-14 04:09:51 -04:00
|
|
|
over encoder? [ >r encoder-stream r> ] when <encoder> ;
|
2008-02-15 20:44:35 -05:00
|
|
|
|
2008-02-21 16:22:49 -05:00
|
|
|
: redecode ( stream encoding -- newstream )
|
2008-03-14 04:09:51 -04:00
|
|
|
over decoder? [ >r decoder-stream r> ] when <decoder> ;
|
|
|
|
PRIVATE>
|
2008-02-21 16:22:49 -05:00
|
|
|
|
2008-03-04 22:05:58 -05:00
|
|
|
: <encoder-duplex> ( stream-in stream-out encoding -- duplex )
|
2008-02-24 02:37:05 -05:00
|
|
|
tuck reencode >r redecode r> <duplex-stream> ;
|