base32: change to RFC 3548 version.
parent
ab88710e74
commit
d53ef800e2
|
@ -1,20 +1,22 @@
|
|||
! Copyright (C) 2019 John Benediktsson
|
||||
! See http://factorcode.org/license.txt for BSD license
|
||||
|
||||
USING: base32 tools.test ;
|
||||
USING: base32 sequences tools.test ;
|
||||
|
||||
{ "16J" } [ 1234 base32> ] unit-test
|
||||
{ "16JD" } [ 1234 base32-checksum> ] unit-test
|
||||
{ "0" } [ 0 base32> ] unit-test
|
||||
{ "00" } [ 0 base32-checksum> ] unit-test
|
||||
[ -1 base32> ] must-fail
|
||||
[ 1.0 base32> ] must-fail
|
||||
{ B{ } } [ f >base32 ] unit-test
|
||||
{ B{ } } [ B{ } >base32 ] unit-test
|
||||
{ "AA======" } [ "\0" >base32 "" like ] unit-test
|
||||
{ "ME======" } [ "a" >base32 "" like ] unit-test
|
||||
{ "MFRA====" } [ "ab" >base32 "" like ] unit-test
|
||||
{ "MFRGG===" } [ "abc" >base32 "" like ] unit-test
|
||||
{ "MFRGGZA=" } [ "abcd" >base32 "" like ] unit-test
|
||||
{ "MFRGGZDF" } [ "abcde" >base32 "" like ] unit-test
|
||||
|
||||
{ 1234 } [ "16J" >base32 ] unit-test
|
||||
{ 1234 } [ "I6J" >base32 ] unit-test
|
||||
{ 1234 } [ "i6J" >base32 ] unit-test
|
||||
{ 1234 } [ "16JD" >base32-checksum ] unit-test
|
||||
{ 1234 } [ "I6JD" >base32-checksum ] unit-test
|
||||
{ 1234 } [ "i6JD" >base32-checksum ] unit-test
|
||||
{ 0 } [ "0" >base32 ] unit-test
|
||||
{ 0 } [ "00" >base32-checksum ] unit-test
|
||||
{ B{ } } [ f base32> ] unit-test
|
||||
{ B{ } } [ B{ } base32> ] unit-test
|
||||
{ "\0" } [ "AA======" base32> "" like ] unit-test
|
||||
{ "a" } [ "ME======" base32> "" like ] unit-test
|
||||
{ "ab" } [ "MFRA====" base32> "" like ] unit-test
|
||||
{ "abc" } [ "MFRGG===" base32> "" like ] unit-test
|
||||
{ "abcd" } [ "MFRGGZA=" base32> "" like ] unit-test
|
||||
{ "abcde" } [ "MFRGGZDF" base32> "" like ] unit-test
|
||||
|
|
|
@ -1,42 +1,77 @@
|
|||
! Copyright (C) 2019 John Benediktsson
|
||||
! See http://factorcode.org/license.txt for BSD license
|
||||
|
||||
USING: ascii assocs byte-arrays kernel literals math sequences ;
|
||||
|
||||
USING: base64.private byte-arrays combinators fry io io.binary
|
||||
io.encodings.binary io.streams.byte-array kernel literals math
|
||||
namespaces sequences ;
|
||||
IN: base32
|
||||
|
||||
ERROR: malformed-base32 ;
|
||||
|
||||
! XXX: Optional map 0 as O
|
||||
! XXX: Optional map 1 as L or I
|
||||
! XXX: Optional handle lower-case input
|
||||
|
||||
<PRIVATE
|
||||
|
||||
<<
|
||||
CONSTANT: ALPHABET $[ "0123456789ABCDEFGHJKMNPQRSTVWXYZ" >byte-array ]
|
||||
CONSTANT: alphabet $[ "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" >byte-array ]
|
||||
>>
|
||||
CONSTANT: INVERSE $[ 256 [ ALPHABET index 0xff or ] B{ } map-integers ]
|
||||
CONSTANT: CHECKSUM $[ ALPHABET "*~$=U" append ]
|
||||
|
||||
: normalize-base32 ( seq -- seq' )
|
||||
CHAR: - swap remove >upper H{
|
||||
{ CHAR: I CHAR: 1 }
|
||||
{ CHAR: L CHAR: 1 }
|
||||
{ CHAR: O CHAR: 0 }
|
||||
} substitute ;
|
||||
: ch>base32 ( ch -- ch )
|
||||
alphabet nth ; inline
|
||||
|
||||
: parse-base32 ( seq -- base32 )
|
||||
0 swap [ [ 32 * ] [ INVERSE nth + ] bi* ] each ;
|
||||
: base32>ch ( ch -- ch )
|
||||
$[ alphabet alphabet-inverse 0 CHAR: = pick set-nth ] nth
|
||||
[ malformed-base32 ] unless* ; inline
|
||||
|
||||
: encode5 ( seq -- byte-array )
|
||||
be> { -35 -30 -25 -20 -15 -10 -5 0 } '[
|
||||
shift 0x1f bitand ch>base32
|
||||
] with B{ } map-as ; inline
|
||||
|
||||
: encode-pad ( seq n -- byte-array )
|
||||
[ 5 0 pad-tail encode5 ] [ B{ 0 2 4 5 7 } nth ] bi* head-slice
|
||||
8 CHAR: = pad-tail ; inline
|
||||
|
||||
: (encode-base32) ( stream column -- )
|
||||
5 pick stream-read dup length {
|
||||
{ 0 [ 3drop ] }
|
||||
{ 5 [ encode5 write-lines (encode-base32) ] }
|
||||
[ encode-pad write-lines (encode-base32) ]
|
||||
} case ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: encode-base32 ( -- )
|
||||
input-stream get f (encode-base32) ;
|
||||
|
||||
: encode-base32-lines ( -- )
|
||||
input-stream get 0 (encode-base32) ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: decode8 ( seq -- )
|
||||
[ 0 [ base32>ch swap 5 shift bitor ] reduce 5 >be ]
|
||||
[ [ CHAR: = = ] count ] bi
|
||||
[ write ] [ B{ 0 4 0 3 2 0 1 } nth head-slice write ] if-zero ; inline
|
||||
|
||||
: (decode-base32) ( stream -- )
|
||||
8 "\n\r" pick read-ignoring dup length {
|
||||
{ 0 [ 2drop ] }
|
||||
{ 8 [ decode8 (decode-base32) ] }
|
||||
[ drop 8 CHAR: = pad-tail decode8 (decode-base32) ]
|
||||
} case ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: decode-base32 ( -- )
|
||||
input-stream get (decode-base32) ;
|
||||
|
||||
: >base32 ( seq -- base32 )
|
||||
normalize-base32 parse-base32 ;
|
||||
binary [ binary [ encode-base32 ] with-byte-reader ] with-byte-writer ;
|
||||
|
||||
: base32> ( base32 -- seq )
|
||||
dup 0 < [ non-negative-integer-expected ] when
|
||||
[ dup 0 > ] [
|
||||
32 /mod ALPHABET nth
|
||||
] "" produce-as nip [ "0" ] when-empty reverse! ;
|
||||
binary [ binary [ decode-base32 ] with-byte-reader ] with-byte-writer ;
|
||||
|
||||
: >base32-checksum ( seq -- base32 )
|
||||
normalize-base32 unclip-last [ parse-base32 ] dip
|
||||
CHECKSUM index over 37 mod assert= ;
|
||||
|
||||
: base32-checksum> ( base32 -- seq )
|
||||
[ base32> ] keep 37 mod CHECKSUM nth suffix ;
|
||||
: >base32-lines ( seq -- base32 )
|
||||
binary [ binary [ encode-base32-lines ] with-byte-reader ] with-byte-writer ;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Douglas Crockford's Base 32 encoding/decoding
|
||||
Base 32 encoding/decoding (RFC 3548)
|
||||
|
|
Loading…
Reference in New Issue