RosettaCodeData/Task/Base64-decode-data/Forth/base64-decode-data.fth

35 lines
1.1 KiB
Forth

variable bitsbuff
: char>6bits ( c -- u )
dup 43 = if drop 62 exit then ( + case )
dup 47 = if drop 63 exit then ( / case )
dup 48 58 within if 48 - 52 + exit then ( 0-9 case )
dup 65 91 within if 65 - exit then ( A-Z case )
dup 97 123 within if 97 - 26 + exit then ( a-z case )
drop 0 ( padding )
;
: 6bitsin ( v -- ) bitsbuff @ 6 lshift + bitsbuff ! ;
: 4charsin ( addr -- addr+4 )
$0 bitsbuff !
dup 4 + dup rot
do I c@ char>6bits 6bitsin loop ;
: 3bytes, ( -- )
bitsbuff @ 16 rshift $ff and c,
bitsbuff @ 8 rshift $ff and c,
bitsbuff @ $ff and c, ;
: b64dec ( addr1 n1 -- addr2 n2 )
here rot rot ( addr2 addr1 n1 )
4 / ( addr2 addr1 n1/4 )
0 do
4charsin 3bytes,
loop ( addr2 addr1+4x )
( get back for padding )
1 - dup c@ 61 = if 1 else 0 then swap ( addr2 0|1 addr1+4x-1 )
1 - c@ 61 = if 1 else 0 then + ( addr2 0|1|2 )
swap ( 0|1|2 addr2 )
dup here swap - ( 0|1|2 addr2 n' )
rot - ( addr2 n2 )
;