64 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			64 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Factor
		
	
	
| ! Copyright (C) 2013-2014 Björn Lindqvist
 | |
| ! See http://factorcode.org/license.txt for BSD license
 | |
| USING: accessors ascii base64 fry grouping.extras io
 | |
| io.encodings io.encodings.string io.encodings.utf16 kernel math
 | |
| math.functions sequences splitting strings ;
 | |
| IN: io.encodings.utf7
 | |
| 
 | |
| TUPLE: utf7codec dialect buffer ;
 | |
| 
 | |
| ! These words encodes the difference between standard utf7 and the
 | |
| ! dialect used by IMAP which wants slashes replaced with commas when
 | |
| ! encoding and uses '&' instead of '+' as the escaping character.
 | |
| : utf7 ( -- utf7codec )
 | |
|     {
 | |
|         { { } { } }
 | |
|         { { CHAR: + } { CHAR: - } }
 | |
|     } V{ } utf7codec boa ;
 | |
| 
 | |
| : utf7imap4 ( -- utf7codec )
 | |
|     {
 | |
|         { { CHAR: / } { CHAR: , } }
 | |
|         { { CHAR: & } { CHAR: - } }
 | |
|     } V{ } utf7codec boa ;
 | |
| 
 | |
| : >raw-base64 ( bytes -- bytes' )
 | |
|     >string utf16be encode >base64 [ CHAR: = = ] trim-tail ;
 | |
| 
 | |
| : raw-base64> ( str -- str' )
 | |
|     dup length 4 / ceiling 4 * CHAR: = pad-tail base64> utf16be decode ;
 | |
| 
 | |
| : encode-chunk ( repl-pair surround-pair chunk ascii? -- bytes )
 | |
|     [ swap [ first ] [ concat ] bi replace nip ]
 | |
|     [ >raw-base64 -rot [ first2 replace ] [ first2 surround ] bi* ] if ;
 | |
| 
 | |
| : encode-utf7-string ( str codec -- bytes )
 | |
|     [ [ printable? ] group-by ] dip
 | |
|     dialect>> first2 '[ _ _ rot first2 swap encode-chunk ] map
 | |
|     B{ } concat-as ;
 | |
| 
 | |
| M: utf7codec encode-string ( str stream codec -- )
 | |
|     swapd encode-utf7-string swap stream-write ;
 | |
| 
 | |
| DEFER: emit-char
 | |
| 
 | |
| : decode-chunk ( dialect -- ch buffer )
 | |
|     dup first2 swap [ second read-until drop ] [ first2 swap replace ] bi*
 | |
|     [ second first first { } ] [ raw-base64> emit-char ] if-empty ;
 | |
| 
 | |
| : fill-buffer ( dialect -- ch buffer )
 | |
|     dup second first first read1 dup swapd = [
 | |
|         drop decode-chunk
 | |
|     ] [ nip { } ] if ;
 | |
| 
 | |
| : emit-char ( dialect buffer -- ch buffer' )
 | |
|     [ fill-buffer ] [ nip unclip swap ] if-empty ;
 | |
| 
 | |
| : replace-all! ( src dst -- )
 | |
|     [ delete-all ] keep push-all ;
 | |
| 
 | |
| M: utf7codec decode-char ( stream codec -- char/f )
 | |
|     swap [
 | |
|         [ dialect>> ] [ buffer>> ] bi [ emit-char ] keep replace-all!
 | |
|     ] with-input-stream ;
 |