stack-machine/asm/lib/base64.txt

148 lines
3.0 KiB
Plaintext

## vim: set sw=3 expandtab:
# ( ... get_char store_byte -- end_char )
# get_char: ( ... -- ... char )
# store_byte: ( ... byte -- ... )
decode_base64:
push
push
immed 0
immed 0
.loop: # ( n bits // gc sb )
rdup
pop
swap
push
swap
push # ( gc // n bits gc sb )
call # ( ch // n bits gc sb )
dup; immed 10; sub
jump .not_nl rel ne drop
drop
pop
pop
jump .loop # ( n bits // gc sb )
.not_nl: # ( ch // n bits gc sb )
dup; immed '='; sub
jump .pad rel eq drop
dup
call decode_char # ( ch val // n bits gc sb )
jump .invalid rel lt
nip # ( val // n bits gc sb )
pop
swap
pop # ( n val bits // gc sb )
or
immed -6
rshift # ( n bits' // gc sb ) [ bits' = (bits|val)<<6 ]
push
immed 6
add # ( n' // bits' gc sb ) [ n' = n + 6 ]
dup; immed 8; sub
jump .store rel ge # ( n' (n'-8) // bits' gc sb )
drop
pop
jump .loop rel # ( n' bits' // gc sb )
.store: # ( n' (n'-8) // bits' gc sb )
nip
dup # ( n'' (n'-8) // bits' gc sb ) [ n'' = n'-8 ]
rdup
pop
swap # ( n'' bits' (n'-8) // bits' gc sb )
immed 6
add
rshift # ( n'' byte // bits' gc sb )
swap
pop
pop
rdup
pop # ( byte n'' bits' gc sb // sb )
swap
push
swap
push
swap
push # ( byte sb // n'' bits' gc sb )
call # ( // n'' bits' gc sb )
pop
pop
jump .loop # ( n'' bits' // gc sb )
.pad: # ( ch // n bits gc sb )
# reset accumulated state
drop
rdrop
rdrop
immed 0
immed 0
# continue until something non-base64 is received
jump .loop # ( n bits // gc sb )
.invalid: # ( ch val // n bits gc sb )
drop
rdrop
rdrop
rdrop
rdrop
return # ( ch // )
# ( val low high -- (low<=val<=high) )
in_range:
over
sub
push # ( val low // (high-low) )
sub
jump .too_low rel lt
pop # ( (val-low) (high-low) // )
sub
jump .too_high rel gt drop
immed 1
return
.too_low: # ( (val-low) // (high-low) )
drop
rdrop
.too_high:
immed 0
return
decode_char:
dup; immed 'A'; immed 'Z'
call in_range
jump .uc rel ne drop
dup; immed 'a'; immed 'z'
call in_range
jump .lc rel ne drop
dup; immed '0'; immed '9'
call in_range
jump .digit rel ne drop
dup; immed '+'; sub
jump .plus rel eq drop
dup; immed '/'; sub
jump .slash rel eq drop
.invalid:
immed -1
nip return
.uc:
immed 65 # 'A' == 65, base64['A'] == 0
sub return
.lc:
immed 71 # 'a' == 97, base64['a'] == 26
sub return
.digit:
immed 4 # '0' == 48, base64['0'] == 52
add return
.plus:
immed 62
nip return
.slash:
immed 63
nip return