123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160(*
* Copyright 2011 The Savonet Team
*
* This file is part of ocaml-mm.
*
* ocaml-mm 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 of the License, or
* (at your option) any later version.
*
* ocaml-mm 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ocaml-mm; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* As a special exception to the GNU Library General Public License, you may
* link, statically or dynamically, a "work that uses the Library" with a publicly
* distributed version of the Library to produce an executable file containing
* portions of the Library, and distribute that executable file under terms of
* your choice, without any of the additional requirements listed in clause 6
* of the GNU Library General Public License.
* By "a publicly distributed version of the Library", we mean either the unmodified
* Library as distributed by The Savonet Team, or a modified version of the Library that is
* distributed under the conditions defined in clause 3 of the GNU Library General
* Public License. This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU Library General Public License.
*
*)moduletypeBuffer=sigtypetvalcreate:int->tvalblit:t->int->t->int->int->unitendmoduletypeR=sigtypebuffertypetvalcreate:int->tvalread_space:t->intvalwrite_space:t->intvalread_advance:t->int->unitvalwrite_advance:t->int->unitvalread:t->buffer->int->int->unitvalpeek:t->buffer->int->int->unitvalwrite:t->buffer->int->int->unitvaltransmit:t->(buffer->int->int->int)->intendmoduleMake(B:Buffer)=structtypebuffer=B.ttypet={size:int;buffer:buffer;mutablerpos:int;(** current read position *)mutablewpos:int;(** current write position *)}letcreatesize={(* size + 1 so we can store full buffers, while keeping
rpos and wpos different for implementation matters *)size=size+1;buffer=B.create(size+1);rpos=0;wpos=0;}letread_spacet=ift.wpos>=t.rposthent.wpos-t.rposelset.size-(t.rpos-t.wpos)letwrite_spacet=ift.wpos>=t.rposthent.size-(t.wpos-t.rpos)-1elset.rpos-t.wpos-1letread_advancetn=assert(n<=read_spacet);ift.rpos+n<t.sizethent.rpos<-t.rpos+nelset.rpos<-t.rpos+n-t.sizeletwrite_advancetn=assert(n<=write_spacet);ift.wpos+n<t.sizethent.wpos<-t.wpos+nelset.wpos<-t.wpos+n-t.sizeletpeektbuffofflen=assert(len<=read_spacet);letpre=t.size-t.rposinletextra=len-preinifextra>0then(B.blitt.buffert.rposbuffoffpre;B.blitt.buffer0buff(off+pre)extra)elseB.blitt.buffert.rposbuffofflenletreadtbuffofflen=peektbuffofflen;read_advancetlenletwritetbuffofflen=assert(len<=write_spacet);letpre=t.size-t.wposinletextra=len-preinifextra>0then(B.blitbuffofft.buffert.wpospre;B.blitbuff(off+pre)t.buffer0extra)elseB.blitbuffofft.buffert.wposlen;write_advancetlenlettransmittf=ift.wpos=t.rposthen0else(letlen0=ift.wpos>=t.rposthent.wpos-t.rposelset.size-t.rposinletlen=ft.buffert.rposlen0inassert(len<=len0);read_advancetlen;len)endmoduleMake_ext(B:Buffer)=structmoduleR=Make(B)typebuffer=R.buffertypet={mutableringbuffer:R.t}letpreparebuflen=ifR.write_spacebuf.ringbuffer>=lenthenbuf.ringbufferelse(letrb=R.create(R.read_spacebuf.ringbuffer+len)inwhileR.read_spacebuf.ringbuffer<>0doignore(R.transmitbuf.ringbuffer(funbufofslen->R.writerbbufofslen;len))done;buf.ringbuffer<-rb;rb)letpeekrb=R.peekrb.ringbufferletreadrb=R.readrb.ringbufferletwriterbbufofslen=letrb=preparerbleninR.writerbbufofslenlettransmitrb=R.transmitrb.ringbufferletread_spacerb=R.read_spacerb.ringbufferletwrite_spacerb=R.write_spacerb.ringbufferletread_advancerb=R.read_advancerb.ringbufferletwrite_advancerb=R.write_advancerb.ringbufferletcreatelen={ringbuffer=R.createlen}end