Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file decompress_lz77.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362moduleSafe=Decompress_safemoduleSeq=Decompress_seqmoduleHunk=Decompress_hunkmoduleB=Decompress_bletpf=Format.fprintfletrepeatatm=letatm=Char.codeatm|>Int64.of_intinlet(lor)=Int64.logorinlet(lsl)=Int64.shift_leftinatmlor(atmlsl8)lor(atmlsl16)lor(atmlsl24)lor(atmlsl32)lor(atmlsl40)lor(atmlsl48)lor(atmlsl56)typeerror=Invalid_levelofint|Invalid_wbitsofintletpp_errorfmt=function|Invalid_levellevel->Format.fprintffmt"(Invalid_level %d)"level|Invalid_wbitswbits->Format.fprintffmt"(Invalid_wbits %d)"wbitsexceptionMatchofint*intexceptionLiteralofcharexceptionBreaktype'it={i_off:int;i_pos:int;i_len:int;level:int;on:Hunk.t->unit;state:'istate;witness:'iB.t}and'istate=|Deflateofint|Deffastofint|Chooseofint|Exceptionoferrorand'ires=|Contof'it|Waitof'it*Hunk.tSeq.t|Errorof'it*error(* XXX: we don't have an [Ok] result because this algorithm does not decide if
you need to stop the compression or not - this is decided by the user. It's
illogic to force a [`End] state with this algorithm. *)letpp_stateppf=function|Deflatewbits->pfppf"(Deflate wbits:%d)"wbits|Deffastwbits->pfppf"(Deffast wbits:%d)"wbits|Choosewbits->pfppf"(Choose wbits:%d)"wbits|Exceptionexn->pfppf"(Exception @[%a@])"pp_errorexnletppppf{i_off;i_pos;i_len;level;state;_}=pfppf"{@[<hov>i_off = %d;@ i_pos = %d;@ i_len = %d;@ level = %d;@ on = #fun;@ \
state = @[%a@]@]}"i_offi_posi_lenlevelpp_statestateletawaittlst:'ires=Wait(t,lst)leterrortexn:'ires=Error({twithstate=Exceptionexn},exn)let_max_distance=8191let_max_length=256let_size_of_int64=8let_idx_boundary=2typekey=int32optionletkeywitnesssrcidxlen:key=ifidx<len-3thenSome(Safe.get_32witnesssrcidx)elseNonemoduleT=structletfindtablex=tryHashtbl.findtablexwithNot_found->[]letaddkeyvaluetable=letrest=findtablekeyinHashtbl.replacetablekey(value::rest)endletlonguest_substringwitnesssrcxylen=letrecauxaccl=ifl<_max_length&&x+l<y&&y+l<len&&Safe.getwitnesssrc(x+l)=Safe.getwitnesssrc(y+l)thenaux(Some(l+1))(l+1)elseaccinauxNone0(* XXX: from ocaml-lz77, no optimized but this algorithm has no constraint.
bisoux @samoht. *)letdeflate?(max_fardistance=(1lsl15)-1)srct=letresults=Queue.create()inletsrc_idx=ref(t.i_off+t.i_pos)inlettable=Hashtbl.create1024inletlast=ref0inletflush_last()=if!last<>0then(fori=0to!last-1dolethunk=Hunk.Literal(Safe.gett.witnesssrc(!src_idx-!last+i))int.onhunk;Queue.pushhunkresultsdone;last:=0)inletfind_matchidx=letmaxab=matcha,bwith|Some(_,x),Some(_,y)->ifx>=ythenaelseb|Some_,None->a|None,Some_->b|None,None->Noneinletkey=keyt.witnesssrcidx(t.i_off+t.i_len)inletcandidates=T.findtablekeyinletrecauxacc=function|[]->acc|x::r->(ifx>=idx||idx-x>=max_fardistancethenaccelsematchlonguest_substringt.witnesssrcxidx(t.i_off+t.i_len)with|Somelenwhenlen>=3->aux(maxacc(Some(x,len)))r|_->auxaccr)inmatchauxNonecandidateswith|None->None|Some(i,len)->Some(idx-i,len)inwhile!src_idx<t.i_off+t.i_lendomatchfind_match!src_idxwith|None->T.add(keyt.witnesssrc!src_idx(t.i_off+t.i_len))!src_idxtable;incrlast;incrsrc_idx|Some(start,len)->fori=!src_idxto!src_idx+len-1doT.add(keyt.witnesssrci(t.i_off+t.i_len))itabledone;flush_last();t.on(Hunk.Match(len-3,start-1));Queue.push(Hunk.Match(len-3,start-1))results;src_idx:=!src_idx+lendone;flush_last();Seq.of_queueresultslet_hlog=[|0;11;11;11;12;13;13;13;13;13|](* Same as blosclz, fast and imperative implementation *)letdeffast:typea.?accel:int->?max_fardistance:int->(Safe.ro,a)Safe.t->at->Hunk.tSeq.t=fun?(accel=1)?(max_fardistance=(1lsl15)-1)srct->letsrc_idx=ref(t.i_off+t.i_pos)inlethash_log=_hlog.(t.level)inlethash_len=1lslhash_loginlethash_tab=Array.makehash_len0inletresults=Queue.create()inletaccel=ifaccel<1then0elseaccel-1int.on(Hunk.Literal(Safe.gett.witnesssrc!src_idx));Queue.push(Hunk.Literal(Safe.gett.witnesssrc!src_idx))results;incrsrc_idx;t.on(Hunk.Literal(Safe.gett.witnesssrc!src_idx));Queue.push(Hunk.Literal(Safe.gett.witnesssrc!src_idx))results;incrsrc_idx;letcrefidx=tryifSafe.gett.witnesssrc!ref=Safe.gett.witnesssrc!idxthen(incrref;incridx;true)elsefalsewith_->falseinwhile!src_idx<t.i_off+t.i_len-12doletanchor=!src_idxinletsrc_ref=ref!src_idxintryifSafe.gett.witnesssrc!src_idx=Safe.gett.witnesssrc(!src_idx-1)&&Safe.get_16t.witnesssrc(!src_idx-1)=Safe.get_16t.witnesssrc(!src_idx+1)thenraise(Match(0,0))(* (+3, +1) *);lethval=letv=Safe.get_16t.witnesssrc!src_idxinletv=Safe.get_16t.witnesssrc(!src_idx+1)lxor(vlsr(16-hash_log))lxorvinvland((1lslhash_log)-1)insrc_ref:=hash_tab.(hval);letdistance=anchor-!src_refinifdistancelandaccel=0thenhash_tab.(hval)<-anchor-t.i_off;ifdistance=0||distance>=max_fardistance||csrc_refsrc_idx=false||csrc_refsrc_idx=false||csrc_refsrc_idx=falsethenraise(Literal(Safe.gett.witnesssrcanchor));ift.level>=5&&distance>=_max_distancethenifcsrc_refsrc_idx=false||csrc_refsrc_idx=falsethenraise(Literal(Safe.gett.witnesssrcanchor))elseraise(Match(2,distance-1))(* (+3, +1) *);raise(Match(!src_idx-anchor-3,distance-1))with|Match(len,0)->(letpattern=Safe.gett.witnesssrc(anchor+len-1)inletv1=repeatpatternin(* _ _ _ _
* |_|_|_|_|
* | | | | src_idx
* | | | src_ref
* | | anchor
* | -1
*)src_idx:=anchor+(len+3);(* XXX: in blosclz, [src_ref = anchor - 1 + 3], but in this case, we
accept 1 wrong byte. *)src_ref:=anchor+(len+3);trywhile!src_idx<t.i_off+t.i_len-_size_of_int64-(2*_idx_boundary)&&!src_idx-3-anchor<_max_length-_size_of_int64doletv2=Safe.get_64t.witnesssrc!src_refinifv1<>v2then(while!src_idx<t.i_off+t.i_len-_idx_boundary&&!src_idx-3-anchor<_max_lengthdoifSafe.gett.witnesssrc!src_ref<>patternthenraiseBreakelse(incrsrc_ref;incrsrc_idx)done;raiseBreak)else(src_idx:=!src_idx+8;src_ref:=!src_ref+8)done;raiseBreakwithBreak->if!src_idx>t.i_off+t.i_len-_idx_boundarythen(letl=!src_idx-(t.i_off+t.i_len)-_idx_boundaryinsrc_idx:=!src_idx-l;src_ref:=!src_ref-l);t.on(Hunk.Match(!src_idx-3-anchor,0));Queue.push(Hunk.Match(!src_idx-3-anchor,0))results)|Match(len,dist)->(src_idx:=anchor+(len+3);src_ref:=anchor-(dist+1)+(len+3);trywhile!src_idx<t.i_off+t.i_len-_size_of_int64-(2*_idx_boundary)&&!src_idx-3-anchor<_max_length-_size_of_int64doifSafe.get_64t.witnesssrc!src_idx<>Safe.get_64t.witnesssrc!src_refthen(while!src_idx<t.i_off+t.i_len-_idx_boundary&&!src_idx-3-anchor<_max_lengthdoifcsrc_refsrc_idx=falsethenraiseBreakdone;raiseBreak)else(src_idx:=!src_idx+8;src_ref:=!src_ref+8)done;raiseBreakwithBreak->if!src_idx>t.i_off+t.i_len-_idx_boundarythen(letl=!src_idx-(t.i_off+t.i_len)-_idx_boundaryinsrc_idx:=!src_idx-l;src_ref:=!src_ref-l);t.on(Hunk.Match(!src_idx-3-anchor,dist));Queue.push(Hunk.Match(!src_idx-3-anchor,dist))results)|Literalchr->src_idx:=anchor+1;t.on(Hunk.Literalchr);Queue.push(Hunk.Literalchr)resultsdone;while!src_idx<t.i_off+t.i_lendo(lethunk=Hunk.Literal(Safe.gett.witnesssrc!src_idx)int.onhunk;Queue.pushhunkresults);incrsrc_idxdone;Seq.of_queueresultsletevalsrct=leteval0t=matcht.statewith|Deflatewbits->ift.i_len>=12thenCont{twithstate=Deffastwbits}elselethunks=deflate~max_fardistance:((1lslwbits)-1)srctinawait{twithstate=Choosewbits;i_pos=t.i_len}hunks|Deffastwbits->ift.i_len>=12thenlethunks=deffast~max_fardistance:((1lslwbits)-1)srctinawait{twithstate=Choosewbits;i_pos=t.i_len}hunkselseCont{twithstate=Deflatewbits}|Choose_->awaittSeq.empty|Exceptionexn->errortexninletrecloopt=matcheval0twith|Contt->loopt|Wait(t,hunks)->`Await(t,hunks)|Error(t,exn)->`Error(t,exn)inlooptletrefillofflent=ift.i_len-t.i_pos=0thenmatcht.statewith|Choosewindow_bits->{twithi_off=off;i_len=len;i_pos=0;state=Deflatewindow_bits}|Deflate_|Deffast_|Exception_->{twithi_off=off;i_len=len;i_pos=0}elseinvalid_arg(Format.sprintf"L.refill: you lost something (pos: %d, len: %d)"t.i_post.i_len)letused_int=t.i_posletdefault~witness?(level=0)?(on=fun_->())wbits=iflevel>=0&&level<=9&&wbits>=8&&wbits<=15then{i_off=0;i_pos=0;i_len=0;level;on;state=Deflatewbits;witness}elseifwbits>=8&&wbits<=15then{i_off=0;i_pos=0;i_len=0;level=0;on;state=Exception(Invalid_levellevel);witness}else{i_off=0;i_pos=0;i_len=0;level=0;on;state=Exception(Invalid_wbitswbits);witness}