factor/core/io/encodings/encodings.factor

165 lines
4.0 KiB
Factor
Raw Normal View History

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.
USING: math kernel sequences sbufs vectors namespaces growable
2008-05-15 00:23:12 -04:00
strings io classes continuations destructors combinators
2008-07-28 23:28:13 -04:00
io.streams.plain splitting byte-arrays
2008-05-15 00:23:12 -04:00
sequences.private accessors ;
2007-09-20 18:09:08 -04:00
IN: io.encodings
! The encoding descriptor protocol
2008-03-14 04:09:51 -04:00
GENERIC: decode-char ( stream encoding -- char/f )
2008-03-14 04:09:51 -04:00
GENERIC: encode-char ( char stream encoding -- )
2008-03-20 21:11:45 -04:00
GENERIC: <decoder> ( stream encoding -- newstream )
2008-06-12 04:49:29 -04:00
: replacement-char HEX: fffd ; inline
2008-02-01 18:45:35 -05:00
TUPLE: decoder stream code cr ;
2008-02-13 02:02:37 -05:00
2008-03-20 16:00:49 -04:00
ERROR: decode-error ;
2008-02-13 18:53:10 -05:00
GENERIC: <encoder> ( stream encoding -- newstream )
TUPLE: encoder stream code ;
2008-03-20 16:00:49 -04:00
ERROR: encode-error ;
! Decoding
M: object <decoder> f decoder boa ;
2008-02-11 00:14:42 -05:00
<PRIVATE
2008-02-13 20:53:53 -05:00
: cr+ t >>cr drop ; inline
2008-02-16 16:35:44 -05:00
: cr- f >>cr drop ; inline
2008-02-13 20:53:53 -05:00
: >decoder< ( decoder -- stream encoding )
[ stream>> ] [ code>> ] bi ; inline
2008-02-13 20:53:53 -05:00
: fix-read1 ( stream char -- char )
over cr>> [
over cr-
dup CHAR: \n = [
drop dup stream-read1
] when
] when nip ; inline
2008-02-13 20:53:53 -05:00
M: decoder stream-read1
dup >decoder< decode-char fix-read1 ;
2008-02-13 20:53:53 -05:00
2008-02-16 16:35:44 -05:00
: fix-read ( stream string -- string )
over cr>> [
2008-02-16 16:35:44 -05:00
over cr-
"\n" ?head [
over stream-read1 [ suffix ] when*
2008-03-14 04:09:51 -04:00
] when
] when nip ; inline
2008-03-14 04:09:51 -04:00
: (read) ( n quot -- n string )
over 0 <string> [
2008-03-14 04:09:51 -04:00
[
2008-08-18 21:13:24 -04:00
slip over
[ swapd set-nth-unsafe f ] [ 3drop t ] if
] 2curry find-integer
] keep ; inline
: finish-read ( n string -- string/f )
{
{ [ over 0 = ] [ 2drop f ] }
{ [ over not ] [ nip ] }
[ swap head ]
} cond ; inline
2008-02-13 20:53:53 -05:00
M: decoder stream-read
tuck >decoder< [ decode-char ] 2curry (read) finish-read 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 ;
: line-ends/eof ( stream str -- str ) f like swap cr- ; inline
: line-ends\r ( stream str -- str ) swap cr+ ; inline
: line-ends\n ( stream str -- str )
over cr>> over empty? and
[ drop dup cr- stream-readln ] [ swap cr- ] if ; inline
: handle-readln ( stream str ch -- str )
{
{ f [ line-ends/eof ] }
{ CHAR: \r [ line-ends\r ] }
{ CHAR: \n [ line-ends\n ] }
} case ; inline
2008-07-18 20:22:59 -04:00
: ((read-until)) ( buf quot: ( -- char stop? ) -- string/f sep/f )
2008-03-14 04:09:51 -04:00
dup call
[ >r drop "" like r> ]
2008-07-18 20:22:59 -04:00
[ pick push ((read-until)) ] if ; inline recursive
2008-07-12 02:08:30 -04:00
: (read-until) ( quot -- string/f sep/f )
100 <sbuf> swap ((read-until)) ; inline
: decoder-read-until ( seps stream encoding -- string/f sep/f )
[ decode-char dup [ dup rot member? ] [ 2drop f t ] if ] 3curry
2008-07-12 02:08:30 -04:00
(read-until) ;
M: decoder stream-read-until >decoder< decoder-read-until ;
2008-02-13 20:53:53 -05:00
2008-07-12 02:08:30 -04:00
: decoder-readln ( stream encoding -- string/f sep/f )
[ decode-char dup [ dup "\r\n" member? ] [ drop f t ] if ] 2curry
(read-until) ;
2008-02-16 16:35:44 -05:00
2008-07-12 02:08:30 -04:00
M: decoder stream-readln dup >decoder< decoder-readln handle-readln ;
2008-02-16 16:35:44 -05:00
M: decoder dispose stream>> dispose ;
2008-03-14 04:09:51 -04:00
2008-02-16 16:35:44 -05:00
! Encoding
M: object <encoder> encoder boa ;
2008-03-14 04:09:51 -04:00
: >encoder< ( encoder -- stream encoding )
[ stream>> ] [ code>> ] bi ; inline
2008-02-16 16:35:44 -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-07-12 02:08:30 -04:00
: decoder-write ( string stream encoding -- )
[ encode-char ] 2curry each ;
M: encoder stream-write
2008-07-12 02:08:30 -04:00
>encoder< decoder-write ;
2008-02-16 16:35:44 -05:00
M: encoder dispose stream>> dispose ;
2008-02-13 20:53:53 -05:00
M: encoder stream-flush stream>> stream-flush ;
2008-03-18 17:01:14 -04:00
INSTANCE: encoder plain-writer
PRIVATE>
2008-02-15 20:44:35 -05:00
2008-06-12 04:49:29 -04:00
GENERIC# re-encode 1 ( stream encoding -- newstream )
M: object re-encode <encoder> ;
M: encoder re-encode [ stream>> ] dip re-encode ;
2008-02-15 20:44:35 -05:00
: encode-output ( encoding -- )
output-stream [ swap re-encode ] change ;
2008-06-12 04:49:29 -04:00
: with-encoded-output ( encoding quot -- )
[ [ output-stream get ] dip re-encode ] dip
with-output-stream* ; inline
GENERIC# re-decode 1 ( stream encoding -- newstream )
M: object re-decode <decoder> ;
M: decoder re-decode [ stream>> ] dip re-decode ;
: decode-input ( encoding -- )
input-stream [ swap re-decode ] change ;
2008-06-12 04:49:29 -04:00
: with-decoded-input ( encoding quot -- )
[ [ input-stream get ] dip re-decode ] dip
with-input-stream* ; inline