    
    ' Very dirty and hack-ish file (de)compression utility example in FreeBASIC,
    ' using a very simple binary file format <header:4="LZmA"><original_size:4><props:5><stream/>
    ' no hashing/integrity checks (LzmaUncompress does its own checks though), single files only..
    '
    ' but I'm sure you can do better :)
    
    ' Usage: example2 -c <source-file> <destination>
    '        example2 -d <source-file> <destination>
    '   
    '   -c: compress source file to destination
    '   -d: decompress source file to destination
    '
    ' uncomment the following line to use LZMA.DLL instead of the static library.
    '   
    ' #define LZMA_DLL
    
    #libpath "lib/win32"
    #include "inc/Lzma.bi"
    
    declare function compressFile (src as string, dst as string) as integer
    declare function decompressFile (src as string, dst as string) as integer
    
    dim as string src, dst
    
    select case ucase(command(1)) 
        case "-C":
            src = command(2)
            dst = command(3)
            if len(dir(src)) then
                end compressFile(src, dst)
            else
                print "file not found `" & src & "'"
            end if
        case "-D":
            src = command(2)
            dst = command(3)
            if len(dir(src)) then
                end decompressFile(src, dst)
            else
                print "file not found `" & src & "'"
            end if
        case "":
            print "Usage: example2 -c <src> <dstination>" 
            print "       example2 -d <src> <dstination>"
            print
            print "   -c: compress src to dstination"
            print "   -d: decompress src to dstination"
        case else
            print "unknown command-line option `" & command(1) &"'"
    end select
    
    end 1
    
    type mem_hdr field = 1
        as integer size ' original stream size
        as byte    props(0 to LZMA_PROPS_SIZE-1)
    end type
    
    function memCompress(byval src as const ubyte ptr, byval llen as uinteger, byref outlen as uinteger) as any ptr
        dim as uinteger dstLen = llen
        dim as mem_hdr ptr hdr = allocate(sizeof(mem_hdr) + dstLen)
        dim dst as ubyte ptr = cast(ubyte ptr, hdr) + sizeof(mem_hdr)
        
        hdr->size = llen
        
        var r = LzmaCompress(dst, dstLen, src, llen, @hdr->props(0), LZMA_PROPS_SIZE)
        
        if r = SZ_OK then
            hdr = reallocate(hdr, sizeof(mem_hdr) + dstLen)
            outlen = dstLen + sizeof(mem_hdr)
            return hdr
        else
            outlen = r
            deallocate(hdr)
            return 0
        end if
    end function
    
    function memDecompress(byval src as ubyte ptr, byval llen as uinteger, byref outlen as uinteger) as any ptr
        var hdr = cast(mem_hdr ptr, src)
        var pSrc = src + sizeof(mem_hdr)
        var dst = allocate(hdr->size)
        
        outlen = hdr->size
        
        var r = LzmaUncompress(dst, outlen, pSrc, llen, @hdr->props(0), LZMA_PROPS_SIZE)
        
        if r = SZ_OK then
            return dst
        else
            deallocate dst
            outlen = r
            return 0
        end if 
        
    end function
    
    function compressFile (src as string, dst as string) as integer
        var ff = freefile
        dim as ubyte ptr pSrc, pDst
        dim as uinteger srcLen, outlen
        
        open src for binary access read as #ff
            srcLen = LOF(ff)
            pSrc = allocate(srcLen)
            if pSrc then
                get #ff,, *pSrc, srcLen
            else
                print "memory allocation error."
                return -1
            end if
        close #ff
        
        print using "compressing `&'(& bytes of data)... "; src; str(srcLen)
        pdst = memCompress(psrc, srclen, outlen)
        
        if pdst then
            print  using "compression done, & bytes, ratio: &%"; str(outlen); str(int(100 * (outlen/srcLen)))
            ff = freefile
            if len(dir(dst)) then kill (dst)
            open dst for binary access write lock write as #ff
                put #ff,, "LZmA"
                put #ff,, *pdst, outlen
            close
            deallocate (psrc)
            deallocate (pdst)
            return 1
        else
            print "compression error, aborting. ("; outlen ; ")"
            deallocate (psrc)
            return 0
        end if
    end function
    
    function decompressFile (src as string, dst as string) as integer
        var ff = freefile
        dim as uinteger srclen, outlen
        dim as ubyte ptr pSrc, pDst
        dim as string * 4 sig
        open src for binary access read as #ff
            get #ff,, sig
            if sig <> "LZmA" then
                print "invalid or corrupt data."
                return 0
            end if
            srclen = LOF(FF) - 4
            pSrc = allocate(srclen)
            if pSrc then
                get #ff,, *pSrc, srclen
            else
                print "memory allocation error."
                return -1
            end if
        close #ff
        
        print using "decompressing `&' (& bytes of data)... "; src; str(srcLen)
        
        pdst = memDecompress(psrc, srclen, outlen)
        
        if pdst then
            print  using "decompression done, & bytes, ratio: &%"; str(outlen); str(int(100 * (outlen/srcLen)))
            ff = freefile
            if len(dir(dst)) then kill (dst)
            open dst for binary access write lock write as #ff
                put #ff,, *pdst, outlen
            close
            deallocate (psrc)
            deallocate (pdst)
            return 1
        else
            print "compression error, aborting. ("; outlen ; ")"
            deallocate (psrc)
            return 0
        end if
        
    end function
    