! Copyright (C) 2023 CapitalEx. ! See https://factorcode.org/license.txt for BSD license. USING: accessors combinators io.encodings.binary io.files kernel math ranges sequences ; IN: ulz TUPLE: decoder data ip out ; : ( file -- decoder ) binary file-contents 0 SBUF"" clone \ decoder boa ; : copy-forward ( src to from -- ) [a..b) dupd [ swap nth swap push ] 2with each ; : next-by ( decoder length -- decoder ) '[ _ + ] change-ip ; inline : next ( decoder -- decoder ) 1 next-by ; inline : current ( decoder -- byte ) [ ip>> ] [ data>> ] bi ?nth ; : current2 ( decoder -- dbyte ) [ current 8 shift ] [ next current ] bi + ; : lit ( decoder length -- ) { [ drop out>> ] [ drop ip>> ] [ swap ip>> + ] [ drop data>> ] } 2cleave subseq append! drop ; : cpy-start ( decoder offset -- i ) neg swap out>> length + ; : cpy ( decoder length offset -- ) { [ 2drop out>> ] [ nip cpy-start ] [ swap [ cpy-start ] dip + ] } 3cleave copy-forward ; GENERIC: interpret ( decoder -- decoder ) M: predicate{ decoder [ current 0xc0 bitand 0x00 = ] } interpret [ current ] [ next ] bi swap 1 + [ lit ] [ next-by ] 2bi ; M: predicate{ decoder [ current 0xc0 bitand 0x80 = ] } interpret [ current 0x3F bitand 4 + ] [ next current 1 + ] [ next ] tri -rot [ cpy ] keepdd ; M: predicate{ decoder [ current 0xc0 bitand 0xc0 = ] } interpret [ current2 0x3FFF bitand 4 + ] [ next current 1 + ] [ next ] tri -rot [ cpy ] keepdd ; : decode ( file -- string ) [ dup current ] [ interpret ] while out>> ;