123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272(* Some code taken from INRIA's buffer module. *)open!ImportopenBigstringincludeBigbuffer_internallet__internal(t:t)=tletlengtht=t.pos(* {[ let invariant t = assert (t.len == Bigstring.length t.bstr) ]} *)letcreaten=letn=max1ninletbstr=Bigstring.createnin{bstr;pos=0;len=n;init=bstr};;letcontentsbuf=Bigstring.to_stringbuf.bstr~len:buf.posletcontents_bytesbuf=Bigstring.to_bytesbuf.bstr~len:buf.posletbig_contentsbuf=subo~len:buf.posbuf.bstrletvolatile_contentsbuf=buf.bstrletadd_charbufc=letpos=buf.posinifpos>=buf.lenthenresizebuf1;buf.bstr.{pos}<-c;buf.pos<-pos+1;;moduleTo_bytes=Test_blit.Make_distinct_and_test(structtypet=charletequal=Char.equalletof_boolb=ifbthen'a'else'b'end)(structtypenonrect=t[@@derivingsexp_of]letcreate~len=lett=createleninfor_=1tolendoadd_chart'a'done;t;;letlength=lengthletsettic=Bigstring.sett.bstricletgetti=Bigstring.gett.bstriend)(structincludeBytesletcreate~len=createlenletunsafe_blit~src~src_pos~dst~dst_pos~len=Bigstring.To_bytes.unsafe_blit~src:src.bstr~src_pos~dst~dst_pos~len;;end)includeTo_bytesmoduleTo_string=Blit.Make_to_string(Bigbuffer_internal)(To_bytes)letnthbufpos=ifpos<0||pos>=buf.postheninvalid_arg"Bigbuffer.nth"elsebuf.bstr.{pos};;letclearbuf=buf.pos<-0letresetbuf=buf.pos<-0;buf.bstr<-buf.init;buf.len<-Bigstring.lengthbuf.bstr;;letadd_substringbufsrc~pos:src_pos~len=ifsrc_pos<0||len<0||src_pos>String.lengthsrc-lentheninvalid_arg"Bigbuffer.add_substring";letnew_pos=buf.pos+leninifnew_pos>buf.lenthenresizebuflen;Bigstring.From_string.blit~src~src_pos~len~dst:buf.bstr~dst_pos:buf.pos;buf.pos<-new_pos;;letadd_subbytesbufsrc~pos:src_pos~len=ifsrc_pos<0||len<0||src_pos>Bytes.lengthsrc-lentheninvalid_arg"Bigbuffer.add_subbytes";letnew_pos=buf.pos+leninifnew_pos>buf.lenthenresizebuflen;Bigstring.From_bytes.blit~src~src_pos~len~dst:buf.bstr~dst_pos:buf.pos;buf.pos<-new_pos;;letadd_bigstringbufsrc=letlen=Bigstring.lengthsrcinletnew_pos=buf.pos+leninifnew_pos>buf.lenthenresizebuflen;Bigstring.blito~src~src_len:len~dst:buf.bstr~dst_pos:buf.pos();buf.pos<-new_pos;;letadd_stringbufsrc=letlen=String.lengthsrcinletnew_pos=buf.pos+leninifnew_pos>buf.lenthenresizebuflen;Bigstring.From_string.blito~src~src_len:len~dst:buf.bstr~dst_pos:buf.pos();buf.pos<-new_pos;;letadd_bytesbufsrc=letlen=Bytes.lengthsrcinletnew_pos=buf.pos+leninifnew_pos>buf.lenthenresizebuflen;Bigstring.From_bytes.blito~src~src_len:len~dst:buf.bstr~dst_pos:buf.pos();buf.pos<-new_pos;;letadd_bufferbuf_dstbuf_src=letlen=buf_src.posinletdst_pos=buf_dst.posinletnew_pos=dst_pos+leninifnew_pos>buf_dst.lenthenresizebuf_dstlen;Bigstring.blito~src:buf_src.bstr~src_len:len~dst:buf_dst.bstr~dst_pos();buf_dst.pos<-new_pos;;letadd_bin_prott(writer:_Bin_prot.Type_class.writer)x=letnew_pos=matchwriter.writet.bstr~pos:t.posxwith|pos->pos|exception_->(* It's likeky that the exception is due to a buffer overflow, so resize the
internal buffer and try again. Technically we could match on
[Bin_prot.Common.Buffer_short] only, however we can't easily enforce that custom
bin_write_xxx functions do raise this particular exception and not
[Invalid_argument] or [Failure] for instance. *)letsize=writer.sizexinift.pos+size>t.lenthenresizetsize;writer.writet.bstr~pos:t.posxint.pos<-new_pos;;letclosing=function|'('->')'|'{'->'}'|_->assertfalse;;(* opening and closing: open and close characters, typically ( and )
k: balance of opening and closing chars
s: the string where we are searching
start: the index where we start the search. *)letadvance_to_closingopeningclosingksstart=letrecadvancekilim=ifi>=limthenraise(Not_found_s[%message"Bigbuffer.add_substitute: cannot find closing delimiter"(opening:char)(closing:char)(start:int)s])elseifChar.equals.[i]openingthenadvance(k+1)(i+1)limelseifChar.equals.[i]closingthenifk=0thenielseadvance(k-1)(i+1)limelseadvancek(i+1)liminadvancekstart(String.lengths);;letadvance_to_non_alphasstart=letrecadvanceilim=ifi>=limthenlimelse(matchs.[i]with|'a'..'z'|'A'..'Z'|'0'..'9'|'_'|'é'|'à'|'á'|'è'|'ù'|'â'|'ê'|'î'|'ô'|'û'|'ë'|'ï'|'ü'|'ç'|'É'|'À'|'Á'|'È'|'Ù'|'Â'|'Ê'|'Î'|'Ô'|'Û'|'Ë'|'Ï'|'Ü'|'Ç'->advance(i+1)lim|_->i)inadvancestart(String.lengths);;(* We are just at the beginning of an ident in s, starting at start. *)letfind_identsstart=matchs.[start]with(* Parenthesized ident ? *)|('('|'{')asc->letnew_start=start+1inletstop=advance_to_closingc(closingc)0snew_startinString.subs~pos:new_start~len:(stop-start-1),stop+1(* Regular ident *)|_->letstop=advance_to_non_alphas(start+1)inString.subs~pos:start~len:(stop-start),stop;;(* Substitute $ident, $(ident), or ${ident} in s,
according to the function mapping f. *)letadd_substitutebuffs=letlim=String.lengthsinletrecsubstpreviousi=ifi<limthen(matchs.[i]with|'$'ascurrentwhenChar.equalprevious'\\'->add_charbufcurrent;substcurrent(i+1)|'$'->letident,next_i=find_idents(i+1)inadd_stringbuf(fident);subst' 'next_i|currentwhenChar.equalprevious'\\'->add_charbuf'\\';add_charbufcurrent;substcurrent(i+1)|'\\'ascurrent->substcurrent(i+1)|current->add_charbufcurrent;substcurrent(i+1))insubst' '0;;moduleFormat=structletformatter_of_bufferbuf=Format.make_formatter(funsposlen->add_substringbufs~pos~len)ignore;;letbprintfbuf=Format.kfprintfignore(formatter_of_bufferbuf)endmodulePrintf=structletbprintfbuf=Printf.ksprintf(add_stringbuf)end