Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file enclosure.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543type('a,'b)bigarray=('a,'b,Bigarray.c_layout)Bigarray.Array1.texternalis_a_sub:('a,'b)bigarray->int->('a,'b)bigarray->int->bool="caml_bigarray_is_a_sub"[@@noalloc]externalbigarray_physically_equal:('a,'b)bigarray->('a,'b)bigarray->bool="caml_bigarray_physically_equal"[@@noalloc](* TODO: replace by [overlap]. *)[@@@warning"-32"]moduletypeV=sigtypetvalpp:tFmt.tvalsentinel:tvalweight:t->intvalmerge:t->t->toptionvalphysically_equal:t->t->boolendmoduleRBQ(V:V)=structmoduleQueue=Ke.Fke.Weightedtypet={a:V.tarray;c:int;m:int;q:(int,Bigarray.int_elt)Queue.t}(* XXX(dinosaure): [ke] is limited to [Bigarray.kind]. We make an [array]
which will contain values and [q] will contain index of them. Length of [a]
is length of [q]. By this way, length is a power of two and [a] follows
same assertions (see [mask]) as [Ke].
[c] will be the cursor in [a]. [m] is the capacity. It's a good example of
[ke] with something else than [Bigarray.kind]. *)letmakecapacity=letq,capacity=Queue.create~capacityBigarray.Intin{a=Array.makecapacityV.sentinel;c=0;m=capacity;q}letppppft=leta=Array.make(Queue.lengtht.q)V.sentinelinletx=ref0inQueue.iter(funi->a.(!x)<-t.a.(i);incrx)t.q;Fmt.pfppf"{ @[<hov>a = %a;@ \
c = %d;@ \
m = %d;@ \
q = %a;@] }"Fmt.(Dump.arrayV.pp)at.ct.m(Queue.dumpFmt.int)t.qletavailablet=Queue.availablet.qletis_emptyt=Queue.is_emptyt.qlet[@inlinealways]maskxt=xland(t.m-1)letpushtv=leti=maskt.ctinmatchQueue.pusht.qiwith|Someq->t.a.(i)<-v;Ok{twithc=succt.c;q;}|None->Errortletshift_exnt=leti,q=Queue.pop_exnt.qin(t.a.(i),{twithq})letconstv=leti=maskt.ctinmatchQueue.const.qiwith|Someq->t.a.(i)<-v;Ok{twithc=succt.c;q;}|None->ErrortexceptionFullletcons_exntv=matchconstvwith|Okt->t|Error_->raiseFullletweightt=Queue.fold(funai->a+V.weightt.a.(i))0t.qletto_listt=letres=ref[]inQueue.rev_iter(funi->res:=t.a.(i)::!res)t.q;!resendletpp_chr=Fmt.using(function'\032'..'\126'asx->x|_->'.')Fmt.charletpp_scalar:typebuffer.get:(buffer->int->char)->length:(buffer->int)->bufferFmt.t=fun~get~lengthppfb->letl=lengthbinfori=0tol/16doFmt.pfppf"%08x: "(i*16);letj=ref0inwhile!j<16doif(i*16)+!j<lthenFmt.pfppf"%02x"(Char.code@@getb((i*16)+!j))elseFmt.pfppf" ";if!jmod2<>0thenFmt.pfppf" ";incrjdone;Fmt.pfppf" ";j:=0;while!j<16doif(i*16)+!j<lthenFmt.pfppf"%a"pp_chr(getb((i*16)+!j))elseFmt.pfppf" ";incrjdone;Fmt.pfppf"@,"donemoduleRBA=Ke.Fke.WeightedmoduleBuffer=structtypet=|BigstringofBigstringaf.t|Stringofstring|Bytesofbytesletppppf=function|Bigstringx->pp_scalar~length:Bigstringaf.length~get:Bigstringaf.getppfx|Stringx->pp_scalar~length:String.length~get:String.getppfx|Bytesx->pp_scalar~length:Bytes.length~get:Bytes.getppfxletweight=function|Bigstringx->Bigstringaf.lengthx|Stringx->String.lengthx|Bytesx->Bytes.lengthxletsubbufferofflen=matchbufferwith|Bigstringx->Bigstring(Bigstringaf.subx~off~len)|Stringx->String(String.subxofflen)|Bytesx->Bytes(Bytes.subxofflen)endmoduleIOVec=structtypet={buffer:Buffer.t;off:int;len:int}letweight{len;_}=lenletppppft=Fmt.pfppf"{ @[<hov>buffer= @[<hov>%a@];@ \
off= %d;@ len= %d;@] }"Buffer.ppt.buffert.offt.lenletsentinel=letdeadbeef="\222\173\190\239"in{buffer=Buffer.Stringdeadbeef;off=0;len=String.lengthdeadbeef}letmakebufferofflen={buffer;off;len}letlength{len;_}=lenletlengthv=List.fold_left(funax->lengthx+a)0letshift{buffer;off;len}n=assert(n<=len);{buffer;off=off+n;len=len-n}letsplit{buffer;off;len}n=assert(n<=len);({buffer=Buffer.subbufferoffn;off=0;len=n},{buffer=Buffer.subbuffer(off+n)(len-n);off=0;len=len-n})letphysically_equalab=matcha,bwith|{buffer=Buffer.Bytesa;_},{buffer=Buffer.Bytesb;_}->a==b|{buffer=Buffer.Bigstringa;_},{buffer=Buffer.Bigstringb;_}->bigarray_physically_equalab|_,_->falseletmergeab=matcha,bwith|{buffer=Buffer.Bytesa';_},{buffer=Buffer.Bytesb';_}->assert(a'==b');ifa.off+a.len=b.offthenSome{buffer=Buffer.Bytesa';off=a.off;len=a.len+b.len}elseNone|{buffer=Buffer.Bigstringa';_},{buffer=Buffer.Bigstringb';_}->assert(bigarray_physically_equala'b');ifa.off+a.len=b.offthenSome{buffer=Buffer.Bigstringa';off=a.off;len=a.len+b.len}elseNone|_,_->NoneendmoduleRBS=RBQ(IOVec)typeemitter=IOVec.tlist->inttypeencoder={sched:RBS.t;write:(char,Bigarray.int8_unsigned_elt)RBA.t;flush:(int*(int->encoder->unit))Ke.Fke.t;written:int;received:int;emitter:emitter}letpp_flushppf_=Fmt.stringppf"#flush"letppppft=Fmt.pfppf"{ @[<hov>sched= @[<hov>%a@];@ \
write= @[<hov>%a@];@ \
flush= @[<hov>%a@];@ \
written= %d;@ \
received= %d;@ \
emitter= #emitter;@] }"RBS.ppt.sched(RBA.pppp_chr)t.write(Ke.Fke.pppp_flush)t.flusht.writtent.receivedletis_emptyt=RBS.is_emptyt.sched(* XXX(dinosaure): [sched] is a queue of [IOVec]. [write] is a
ring-buffer/[Bigstringaf.t]. [flush] is a queue which can contain
user-defined operation at a break point. [written] is how many bytes we
sended to the user (afterwards a *flush* operation). [received] is how many
bytes we received from the user.
The goal is to have two ways to fill output:
- an heavy way with [write_*] operations which will do internally a [blit].
- a soft way with [shedule_*] operations which will store a pointer.
The complexity is under [sched] where it stores pointer from user but pointer
from [write] queue too. Indeed, [write_] operations did not do only a [blit]
but then they store resulted/*blitted* [Bigstringaf.t] part to [sched].
When we want to shift a part of [encoder], **all** buffers are stored in
[sched]. So we need to shift [sched]. However, resulted [IOVec] can be
physically a part of [write]. In this context, we need to shift [write]. *)letcreate~emitterlen=letwrite,_=RBA.create~capacity:lenBigarray.Charin{sched=RBS.make(len*2);write;flush=Ke.Fke.empty;written=0;received=0;emitter}letcheckiovec{write;_}=matchiovecwith|{IOVec.buffer=Buffer.Bigstringx;_}->letbuf=RBA.unsafe_bigarraywriteinletlen=Bigarray.Array1.dimbufinis_a_subx(Bigarray.Array1.dimx)buflen|_->falseletshift_bufferswrittent=letrecgowrittenacct=matchRBS.shift_exnt.schedwith|iovec,shifted->letlen=IOVec.lengthiovecinifwritten>lenthengo(written-len)(iovec::acc){twithsched=shifted;write=ifcheckiovectthenRBA.N.shift_exnt.writelenelset.write}elseifwritten>0thenletlast,rest=IOVec.splitiovecwrittenin(List.rev(last::acc),{twithsched=RBS.cons_exnshiftedrest;write=ifcheckiovectthenRBA.N.shift_exnt.write(IOVec.lengthlast)elset.write})else(List.revacc,t)|exceptionRBS.Queue.Empty->(List.revacc,t)ingowritten[]tletshift_flusheswrittent=letrecgot=trylet(threshold,f),flush=Ke.Fke.pop_exnt.flushinifcompare(t.written+written-min_int)(threshold-min_int)>=0thenlet()=fwritten{twithflush}ingo{twithflush}elsetwithKe.Fke.Empty->tingotletshiftnt=letlst,t=shift_buffersntin(lst,lett=shift_flushes(IOVec.lengthvlst)tin{twithwritten=t.written+n})lethast=RBS.weightt.schedletdraindraint=letrecgorestt=matchRBS.shift_exnt.schedwith|iovec,shifted->letlen=IOVec.lengthiovecinifrest>=lenthengo(rest-len){twithsched=shifted;write=ifcheckiovectthenRBA.N.shift_exnt.writelenelset.write}else{twithsched=RBS.cons_exnshifted(IOVec.shiftiovecrest);write=ifcheckiovectthenRBA.N.shift_exnt.writerestelset.write}|exceptionRBS.Queue.Empty->tinlett=godraintin{twithwritten=t.written+drain}letflushkt=lett=shift_flushes(hast)tinletn=t.emitter(RBS.to_listt.sched)inlett=drainntink{twithwritten=t.written+n}letrecschedulek~length~buffer?(off=0)?lenvt=letlen=matchlenwithSomelen->len|None->lengthv-offinmatchRBS.pusht.sched(IOVec.make(bufferv)offlen)with|Oksched->(* TODO: merge [Bigstringaf.t]. *)k{twithsched;received=t.received+len}|Error_->letmax=RBS.availablet.schedinletkt=(schedule[@tailcall])k~length~buffer~off:(off+max)~len:(len-max)vtinschedule(flushk)~length~buffer~off~len:maxvtexternalidentity:'a->'a="%identity"letkschedule_string=letlength=String.lengthinletbufferx=Buffer.Stringxinfunkt?(off=0)?lenv->schedulek~length~buffer~off?lenvtletschedule_string=kschedule_stringidentityletkschedule_bytes=letlength=Bytes.lengthinletbufferx=Buffer.Bytesxinfunkt?(off=0)?lenv->schedulek~length~buffer~off?lenvtletschedule_bytes=kschedule_bytesidentityletkschedule_bigstring=letlength=Bigarray.Array1.diminletbufferx=Buffer.Bigstringxinfunkt?(off=0)?lenv->schedulek~length~buffer~off?lenvtletschedule_bigstring=kschedule_bigstringidentityletschedule_flushft={twithflush=Ke.Fke.pusht.flush(t.received,f)}letkschedulevklt=letrecgot=function|[]->kt|(length,off,len,buffer)::r->schedule(funt->(go[@tailcall])tr)~length?off?len~buffer:identitybuffertingotlletschedulev=kschedulevidentityletkschedulev_bigstringklt=letrecgot=function|[]->kt|buffer::r->kschedule_bigstring(funt->(go[@tailcall])tr)tbufferingotlletschedulev_bigstring=kschedulev_bigstringidentityletreckwritek~blit~length?(off=0)?lenbuffert=letlen=matchlenwithSomelen->len|None->lengthbuffer-offinletavailable=RBA.availablet.writein(* XXX(dinosaure): we can factorize the first and the second branch. *)ifavailable>=lenthenletareas,write=RBA.N.push_exnt.write~blit~length~off~lenbufferinkschedulev_bigstringkareas{twithwrite}elseifavailable>0thenletkt=(kwrite[@tailcall])k~blit~length~off:(off+available)~len:(len-available)buffertinletareas,write=RBA.N.push_exnt.write~blit~length~off~len:availablebufferinkschedulev_bigstring(flushk)areas{twithwrite}elseletkt=(kwrite[@tailcall])k~blit~length~off~lenbuffertinflushktletwrite=kwriteidentityletkwritevklt=letrecgot=function|[]->kt|(blit,length,off,len,buffer)::r->kwrite(funt->(go[@tailcall])tr)~blit~length?off?lenbuffertingotlletbigarray_blit_from_stringsrcsrc_offdstdst_offlen=Bigstringaf.blit_from_stringsrc~src_offdst~dst_off~lenletbigarray_blit_from_bytessrcsrc_offdstdst_offlen=Bigstringaf.blit_from_bytessrc~src_offdst~dst_off~lenletbigarray_blitsrcsrc_offdstdst_offlen=Bigarray.Array1.(blit(subsrcsrc_offlen)(subdstdst_offlen))letbigarray_blit_to_bytessrcsrc_offdstdst_offlen=Bigstringaf.blit_to_bytessrc~src_offdst~dst_off~lenletkwrite_string=letlength=String.lengthinletblit=bigarray_blit_from_stringinfunk?(off=0)?lenat->kwritek~blit~length~off?lenatletwrite_string=kwrite_stringidentityletkwrite_bytes=letlength=Bytes.lengthinletblit=bigarray_blit_from_bytesinfunk?(off=0)?lenat->kwritek~blit~length~off?lenatletwrite_bytes=kwrite_bytesidentityletkwrite_bigstring=letlength=Bigarray.Array1.diminletblit=bigarray_blitinfunk?(off=0)?lenat->kwritek~blit~length~off?lenatletwrite_bigstring=kwrite_bigstringidentityletkwrite_char=letlength_=assertfalseinletblitsrcsrc_offdstdst_offlen=assert(src_off=0);assert(len=1);Bigstringaf.setdstdst_offsrcinfunkat->kwritek~length~blit~off:0~len:1atletwrite_char=kwrite_charidentityletkwrite_uint8=letlength_=assertfalseinletblitsrcsrc_offdstdst_offlen=assert(src_off=0);assert(len=1);Bigstringaf.setdstdst_off(Char.unsafe_chrsrc)infunkat->kwritek~length~blit~off:0~len:1atletwrite_uint8=kwrite_uint8identitymoduletypeS=sigvalkwrite_uint16:(encoder->'v)->int->encoder->'vvalwrite_uint16:int->encoder->encodervalkwrite_uint32:(encoder->'v)->int32->encoder->'vvalwrite_uint32:int32->encoder->encodervalkwrite_uint64:(encoder->'v)->int64->encoder->'vvalwrite_uint64:int64->encoder->encoderendmoduletypeENDIAN=sigtypet=Bigstringaf.tvalset_int16:t->int->int->unitvalset_int32:t->int->int32->unitvalset_int64:t->int->int64->unitendmoduleMake(X:ENDIAN):S=structlet_length_=assertfalseletkwrite_uint16=letlength=_lengthinletblitsrcsrc_offdstdst_offlen=assert(src_off=0);assert(len=2);X.set_int16dstdst_offsrcinfunkat->kwritek~length~blit~off:0~len:2atletwrite_uint16=kwrite_uint16identityletkwrite_uint32=letlength=_lengthinletblitsrcsrc_offdstdst_offlen=assert(src_off=0);assert(len=4);X.set_int32dstdst_offsrcinfunkat->kwritek~length~blit~off:0~len:4atletwrite_uint32=kwrite_uint32identityletkwrite_uint64=letlength=_lengthinletblitsrcsrc_offdstdst_offlen=assert(src_off=0);assert(len=8);X.set_int64dstdst_offsrcinfunkat->kwritek~length~blit~off:0~len:8atletwrite_uint64=kwrite_uint64identityendmoduleLE'=structtypet=Bigstringaf.tletset_int16=Bigstringaf.set_int16_leletset_int32=Bigstringaf.set_int32_leletset_int64=Bigstringaf.set_int64_leendmoduleBE'=structtypet=Bigstringaf.tletset_int16=Bigstringaf.set_int16_beletset_int32=Bigstringaf.set_int32_beletset_int64=Bigstringaf.set_int64_beendmoduleLE=Make(LE')moduleBE=Make(BE')