]> gitweb.factorcode.org Git - factor.git/blob - basis/base64/base64.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / basis / base64 / base64.factor
1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel math sequences io.binary splitting grouping
4 accessors ;
5 IN: base64
6
7 <PRIVATE
8
9 : count-end ( seq quot -- n )
10     trim-right-slice [ seq>> length ] [ to>> ] bi - ; inline
11
12 : ch>base64 ( ch -- ch )
13     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" nth ;
14
15 : base64>ch ( ch -- ch )
16     {
17         f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f
18         f f f f f f f f f f 62 f f f 63 52 53 54 55 56 57 58 59 60 61 f f
19         f 0 f f f 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
20         22 23 24 25 f f f f f f 26 27 28 29 30 31 32 33 34 35 36 37 38 39
21         40 41 42 43 44 45 46 47 48 49 50 51
22     } nth ;
23
24 : encode3 ( seq -- seq )
25     be> 4 <reversed> [
26         -6 * shift HEX: 3f bitand ch>base64
27     ] with B{ } map-as ;
28
29 : decode4 ( str -- str )
30     0 [ base64>ch swap 6 shift bitor ] reduce 3 >be ;
31
32 : >base64-rem ( str -- str )
33     [ 3 0 pad-right encode3 ] [ length 1+ ] bi
34     head-slice 4 CHAR: = pad-right ;
35
36 PRIVATE>
37
38 : >base64 ( seq -- base64 )
39     #! cut string into two pieces, convert 3 bytes at a time
40     #! pad string with = when not enough bits
41     dup length dup 3 mod - cut
42     [ 3 <groups> [ encode3 ] map concat ]
43     [ [ "" ] [ >base64-rem ] if-empty ]
44     bi* append ;
45
46 : base64> ( base64 -- str )
47     #! input length must be a multiple of 4
48     [ 4 <groups> [ decode4 ] map concat ]
49     [ [ CHAR: = = ] count-end ]
50     bi head* ;