35 lines
1.1 KiB
Forth
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 )
|
|
;
|