123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385(*
RES - Automatically Resizing Contiguous Memory for OCaml
Copyright (C) 1999- Markus Mottl
email: markus.mottl@gmail.com
WWW: http://www.ocaml.info
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)moduletypeImplementation=sigtypeeltypetvalname:stringvallength:t->intvalcreate:int->tvalmake:int->el->tvalunsafe_get:t->int->elvalunsafe_set:t->int->el->unitvalunsafe_blit:t->int->t->int->int->unitendmoduleMake(S:Strat.T)(Impl:Implementation)=structmoduleStrategy=Stypestrategy=Strategy.ttypeel=Impl.eltypet={mutablear:Impl.t;mutablevlix:int;mutablestrategy:strategy}letname=Impl.nameletinvalid_argstr=invalid_arg(name^"."^str)letfailwithstr=failwith(name^"."^str)letlengthra=ra.vlix+1letlixra=ra.vlixletreal_lengthra=Impl.lengthra.arletreal_lixra=real_lengthra-1letunsafe_getraix=Impl.unsafe_getra.arixletunsafe_setraixel=Impl.unsafe_setra.arixelletgetran=ifn>ra.vlix||n<0theninvalid_arg"get"elseunsafe_getranletsetranel=ifn>ra.vlix||n<0theninvalid_arg"set"elseunsafe_setranelletcreator=Impl.createletempty_ar=Impl.create0letscreatestrategyn=letres={ar=empty_ar;vlix=n-1;strategy=strategy}inres.ar<-creator(Strategy.growstrategyn);resletsmakestrategynx=letres={ar=empty_ar;vlix=n-1;strategy=strategy}inres.ar<-Impl.make(Strategy.growstrategyn)x;resletcreate_freshn=screateStrategy.defaultnletcreate_fromra={ar=creator(lengthra);vlix=ra.vlix;strategy=ra.strategy}letsemptystrategy=letres={ar=empty_ar;vlix=-1;strategy=strategy}inres.ar<-creator(Strategy.growstrategy0);resletempty()=semptyStrategy.defaultletcreate=screateStrategy.defaultletmake=smakeStrategy.defaultletsinitstrategynf=letres=smakestrategyn(f0)inletar=res.arinfori=1ton-1doImpl.unsafe_setari(fi)done;resletinitnf=sinitStrategy.defaultnfletget_strategyra=ra.strategyletresizersome_lix({ar=ar}asra)len=letnew_ar=creatorleninfori=0tosome_lixdoImpl.unsafe_setnew_ari(Impl.unsafe_getari)done;ra.ar<-new_arletenforce_strategyra=letreal_len=real_lengthrainletnew_len=lengthrainletnew_real_len=Strategy.shrinkra.strategy~real_len~new_leninifnew_real_len<>-1thenresizerra.vlixranew_real_lenletset_strategyrastrategy=ra.strategy<-strategy;enforce_strategyraletput_strategyrastrategy=ra.strategy<-strategyletunsafe_blit_on_otherra1ofs1ra2=Impl.unsafe_blitra1.arofs1ra2.arletcopyra=letlen=lengthrainletar=Impl.createleninImpl.unsafe_blitra.ar0ar0len;{rawithar=ar}letappendra1ra2=matchra1.vlix,ra2.vlixwith|-1,-1->empty()|_,-1->copyra1|-1,_->copyra2|_->letlen1=lengthra1inletlen2=lengthra2inletres=create_fresh(len1+len2)inunsafe_blit_on_otherra10res0len1;unsafe_blit_on_otherra20reslen1len2;resletrecconcat_auxresoffset=function|[]->res|h::t->ifh.vlix<0thenconcat_auxresoffsettelseletlen=lengthhinunsafe_blit_on_otherh0resoffsetlen;concat_auxres(offset+len)tletconcatl=letlen=List.fold_left(funael->a+lengthel)0liniflen=0thenempty()elseconcat_aux(create_freshlen)0lletunsafe_subraofslen=letres=create_freshleninunsafe_blit_on_otherraofsres0len;resletsubraofslen=ifofs<0||len<0||ofs+len>lengthratheninvalid_arg"sub"elseunsafe_subraofslenletguarantee_ixraix=ifreal_lixra<ixthenresizerra.vlixra(Strategy.growra.strategy(ix+1))letmaybe_grow_ixranew_lix=guarantee_ixranew_lix;ra.vlix<-new_lixletadd_onerax=letn=lengthrainmaybe_grow_ixran;unsafe_setranxletunsafe_remove_onera=ra.vlix<-ra.vlix-1;enforce_strategyraletremove_onera=ifra.vlix<0thenfailwith"remove_one"elseunsafe_remove_oneraletunsafe_remove_nran=ra.vlix<-ra.vlix-n;enforce_strategyraletremove_nran=ifn>lengthra||n<0theninvalid_arg"remove_n"elseunsafe_remove_nranletunsafe_remove_rangeraofslen=letofs_len=ofs+leninunsafe_blit_on_otherraofs_lenraofs(lengthra-ofs_len);unsafe_remove_nralenletremove_rangeraofslen=ifofs<0||len<0||ofs+len>lengthratheninvalid_arg"remove_range"elseunsafe_remove_rangeraofslenletclearra=ra.vlix<--1;enforce_strategyraletunsafe_swap{ar=ar}nm=lettmp=Impl.unsafe_getarninImpl.unsafe_setarn(Impl.unsafe_getarm);Impl.unsafe_setarmtmpletswapranm=ifn>ra.vlix||m>ra.vlix||n<0||m<0theninvalid_arg"swap"elseunsafe_swapranmletunsafe_swap_in_last({ar=ar}asra)n=Impl.unsafe_setarn(Impl.unsafe_getarra.vlix);unsafe_remove_oneraletswap_in_lastran=ifn>ra.vlix||n<0theninvalid_arg"swap_in_last"elseunsafe_swap_in_lastranletunsafe_fill({ar=ar}asra)ofslenx=letlast=ofs+len-1inmaybe_grow_ixra(maxlastra.vlix);fori=ofstolastdoImpl.unsafe_setarixdoneletfillraofslenx=ifofs<0||len<0||ofs>lengthratheninvalid_arg"fill"elseunsafe_fillraofslenxletunsafe_blitra1ofs1ra2ofs2len=guarantee_ixra2(ofs2+len-1);unsafe_blit_on_otherra1ofs1ra2ofs2lenletblitra1ofs1ra2ofs2len=iflen<0||ofs1<0||ofs2<0||ofs1+len>lengthra1||ofs2>lengthra2theninvalid_arg"blit"elseunsafe_blitra1ofs1ra2ofs2lenletrecto_list_auxariaccu=ifi<0thenaccuelseto_list_auxar(i-1)(Impl.unsafe_getari::accu)letto_listra=to_list_auxra.arra.vlix[]letrecof_list_auxari=function|[]->()|h::t->Impl.unsafe_setarih;of_list_auxar(i+1)tletof_listl=letra=create_fresh(List.lengthl)inof_list_auxra.ar0l;raletsof_liststrategyl=letra=screatestrategy(List.lengthl)inof_list_auxra.ar0l;raletto_array({ar=ar}asra)=Array.init(lengthra)(funi->Impl.unsafe_getari)letsof_arraystrategyar=sinitstrategy(Array.lengthar)(funi->Array.unsafe_getari)letof_arrayar=sof_arrayStrategy.defaultarletiterf({ar=ar}asra)=fori=0tora.vlixdof(Impl.unsafe_getari)doneletmapf({ar=ar}asra)=letres=create_fromrainletres_ar=res.arinfori=0tores.vlixdoImpl.unsafe_setres_ari(f(Impl.unsafe_getari))done;resletiterif({ar=ar}asra)=fori=0tora.vlixdofi(Impl.unsafe_getari)doneletmapif({ar=ar}asra)=let{ar=res_ar}asres=create_fromrainfori=0tores.vlixdoImpl.unsafe_setres_ari(fi(Impl.unsafe_getari))done;resletfold_leftfaccu({ar=ar}asra)=letres=refaccuinfori=0tora.vlixdores:=f!res(Impl.unsafe_getari)done;!resletfold_rightf({ar=ar}asra)accu=letres=refaccuinfori=ra.vlixdownto0dores:=f(Impl.unsafe_getari)!resdone;!resletrecfor_all_auxipra=i>ra.vlix||p(unsafe_getrai)&&for_all_aux(i+1)praletfor_allpra=for_all_aux0praletrecexists_auxipra=i<=ra.vlix&&(p(unsafe_getrai)||exists_aux(i+1)pra)letexistspra=exists_aux0praletrecmem_auxixra=i<=ra.vlix&&(unsafe_getrai=x||mem_aux(i+1)xra)letmemxra=mem_aux0xraletrecmemq_auxixra=i<=ra.vlix&&(unsafe_getrai==x||memq_aux(i+1)xra)letmemqxra=memq_aux0xraletrecpos_auxixra=ifi>ra.vlixthenNoneelseifunsafe_getrai=xthenSomeielsepos_aux(i+1)xraletposxra=pos_aux0xraletrecposq_auxixra=ifi>ra.vlixthenNoneelseifunsafe_getrai==xthenSomeielseposq_aux(i+1)xraletposqxra=posq_aux0xraletrecfind_auxipra=ifi>ra.vlixthenraiseNot_foundelseletel=unsafe_getraiinifpelthenelelsefind_aux(i+1)praletfindpra=find_aux0praletrecfind_index_auxprai=ifi>ra.vlixthenraiseNot_foundelseifp(unsafe_getrai)thenielsefind_index_auxpra(i+1)letfind_indexprai=ifi<0theninvalid_arg"find_index"elsefind_index_auxprailetfilterp({ar=ar}asra)=letres=semptyra.strategyinfori=0tora.vlixdoletel=Impl.unsafe_getariinifpelthenadd_onereseldone;resletfind_all=filterletfilter_in_placep({ar=ar}asra)=letdest=ref0inletpos=ref0inwhile!pos<=ra.vlixdoletel=Impl.unsafe_getar!posinifpelthenbeginImpl.unsafe_setar!destel;incrdestend;incrposdone;unsafe_remove_nra(!pos-!dest)letpartitionpra=letres1,res2asres=semptyra.strategy,semptyra.strategyinfori=0tora.vlixdoletel=unsafe_getraiinifpelthenadd_oneres1elelseadd_oneres2eldone;resend