123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141(******************************************************************************
* capnp-ocaml
*
* Copyright (c) 2013-2014, Paul Pelzl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************)typefragment={data:string;mutablenext:fragmentoption;}typet={(** String fragments stored in FIFO order *)mutableends:(fragment*fragment)option;(* Front, back *)(** Total byte count of the fragments *)mutablefragments_size:int;}letempty()={ends=None;fragments_size=0;}letadd_fragmentstreamdata=letlen=String.lengthdatainiflen>0then(letfragment={data;next=None}inbeginmatchstream.endswith|Some(old_front,old_back)->old_back.next<-Somefragment;stream.ends<-Some(old_front,fragment)|None->stream.ends<-Some(fragment,fragment)end;stream.fragments_size<-stream.fragments_size+len)letenqueue_frontstreamdata=matchstream.endswith|None->letfragment={data;next=None}instream.ends<-Some(fragment,fragment)|Some(old_front,old_back)->letfragment={data;next=Someold_front}instream.ends<-Some(fragment,old_back)(* Note: does not update [fragments_size] *)letpopstream=matchstream.endswith|None->assert(stream.fragments_size=0);assertfalse|Some(fragment,old_back)->beginmatchfragment.nextwith|None->stream.ends<-None|Somenew_front->stream.ends<-Some(new_front,old_back)end;fragment.dataletof_strings=letstream=empty()inlet()=add_fragmentstreamsinstreamletbyte_countstream=stream.fragments_sizeletremove_exactstreamsize=ifstream.fragments_size<sizethenNoneelseletbuf=Bytes.createsizeinlet()=letofs=ref0inwhile!ofs<sizedoletbytes_remaining=size-!ofsinletfragment=popstreaminletbytes_from_fragment=minbytes_remaining(String.lengthfragment)inBytes.blit(Bytes.unsafe_of_stringfragment)0buf!ofsbytes_from_fragment;beginifbytes_from_fragment<String.lengthfragmentthenletremainder=Util.str_slice~start:bytes_from_fragmentfragmentinenqueue_frontstreamremainderend;ofs:=!ofs+bytes_from_fragment;done;stream.fragments_size<-stream.fragments_size-size;inSome(Bytes.unsafe_to_stringbuf)letremove_at_leaststreamsize=ifstream.fragments_size<sizethenNoneelsebeginletbuffer=Buffer.createsizeinwhileBuffer.lengthbuffer<sizedoBuffer.add_stringbuffer(popstream)done;stream.fragments_size<-stream.fragments_size-(Buffer.lengthbuffer);Some(Buffer.contentsbuffer)endletunremovestreamdata=letlen=String.lengthdatainiflen>0then(enqueue_frontstreamdata;stream.fragments_size<-stream.fragments_size+len;)letpeek_exactstreamsize=matchremove_exactstreamsizewith|Somebytes->unremovestreambytes;Somebytes|None->None