12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788typet={mutablebuffer:Bytes.t;mutablebuffer_length:int;(* = String.length buffer *)mutablelength:int;create_length:int;}(* To help the garbage collector:
* The 'buffer' has a minimum length of 31 bytes. This minimum can still
* be stored in the minor heap.
* The 'buffer' has a length which is always near a multiple of two. This
* limits the number of different bucket sizes, and simplifies reallocation
* of freed memory.
*)(* Optimal string length:
* Every string takes: 1 word for the header, enough words for the
* contents + 1 Null byte (for C compatibility).
* If the buffer grows, it is best to use a new string length such
* that the number of words is exactly twice as large as for the previous
* string.
* n: length of the previous string in bytes
* w: storage size of the previous string in words
* n': length of the new string in bytes
* w' = 2*w: storage size of the new string in words
*
* w = (n+1) / word_length + 1
* [it is assumed that (n+1) is always a multiple of word_length]
*
* n' = (2*w - 1) * word_length - 1
*
* n' = [2 * ( [n+1] / word_length + 1) - 1] * word_length - 1
* = ...
* = (2*n + 2) + word_length - 1
* = 2 * n + word_length + 1
*
* n'+1 is again a multiple of word_length:
* n'+1 = 2*n + 2 + word_length
* = 2*(n+1) + word_length
* = a multiple of word_length because n+1 is a multiple of word_length
*)letword_length=Sys.word_size/8(* in bytes *)letcreaten=letbl=maxn31in{buffer=Bytes.createbl;buffer_length=bl;length=0;create_length=n;}letcontentsb=Bytes.sub_stringb.buffer0b.lengthletto_bytesb=Bytes.subb.buffer0b.lengthletto_tstring_poly:types.t->sNetstring_tstring.tstring_kind->s=funbkind->matchkindwith|Netstring_tstring.String_kind->contentsb|Netstring_tstring.Bytes_kind->to_bytesbletalloc_spacebn=letrecnew_sizes=ifs>=nthenselsenew_size((2*s)+word_length+1)inletsize=min(new_sizeb.buffer_length)Sys.max_string_lengthinifsize<nthenfailwith"Netbuffer: string too large";letbuffer'=Bytes.createsizeinBytes.blitb.buffer0buffer'0b.length;b.buffer<-buffer';b.buffer_length<-sizeletensure_spacebn=(* Ensure that there are n bytes space in b *)ifn>b.buffer_lengththenalloc_spacebnletadd_internalblitbskl=ensure_spaceb(l+b.length);blitskb.bufferb.lengthl;b.length<-b.length+lletadd_substringbskl=ifk<0||l<0||k>String.lengths-ltheninvalid_arg"Netbuffer.add_substring";add_internalBytes.blit_stringbsklletadd_stringbs=add_substringbs0(String.lengths)