123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113(**************************************************************************)(* *)(* OCaml *)(* *)(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1997 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)type('e,'a)t={mutablecount:int;mutabledata:('e,'a)data}and('e,'a)data=Sempty|Sconsof'a*('e,'a)data|Sgenof('e,'a)gen|Sbuffio:buffio->(unit,char)dataand('e,'a)gen={mutablecurr:'aoptionoption;func:'e->'aoption}andbuffio={ic:in_channel;buff:bytes;mutablelen:int;mutableind:int}exceptionFailureletcount{count}=countletfill_buffb=b.len<-inputb.icb.buff0(Bytes.lengthb.buff);b.ind<-0letpeek:typeev.e->(e,v)t->voption=funes->(* consult the first item of s *)matchs.datawithSempty->None|Scons(a,_)->Somea|Sgen{curr=Somea}->a|Sgeng->letx=g.funceing.curr<-Somex;x|Sbuffiob->ifb.ind>=b.lenthenfill_buffb;ifb.len==0thenbegins.data<-Sempty;NoneendelseSome(Bytes.unsafe_getb.buffb.ind)letrecjunk:typeev.e->(e,v)t->unit=funes->matchs.datawithScons(_,d)->s.count<-(succs.count);s.data<-d|Sgen({curr=Some_}asg)->s.count<-(succs.count);g.curr<-None|Sbuffiob->ifb.ind>=b.lenthenfill_buffb;ifb.len==0thens.data<-Semptyelse(s.count<-(succs.count);b.ind<-succb.ind)|Sempty->()|Sgen{curr=None}->matchpeekeswithNone->()|Some_->junkesletrecngetens=ifn<=0then[],s.data,0elsematchpeekeswithSomea->junkes;let(al,d,k)=ngete(predn)sina::al,Scons(a,d),succk|None->[],s.data,0letnpeekens=let(al,d,len)=ngetensins.count<-(s.count-len);s.data<-d;alletnthenst=tryList.nth(npeeke(n+1)st)nwithStdlib.Failure_->raiseFailureletrecnjunkenst=ifn<>0then(junkest;njunke(n-1)st)letnextes=matchpeekeswithSomea->junkes;a|None->raiseFailureletis_emptyes=matchpeekeswith|Some_->false|None->true(* Stream building functions *)letfrom?(offset=0)f={count=offset;data=Sgen{curr=None;func=f}}(* NB we need the thunk for value restriction *)letempty()={count=0;data=Sempty}letof_string?(offset=0)s=letcount=ref0infrom~offset(fun()->letc=!countinifc<String.lengthsthen(incrcount;Somes.[c])elseNone)letof_channelic={count=0;data=Sbuffio{ic=ic;buff=Bytes.create4096;len=0;ind=0}}