123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)(* Byte sequence operations *)(* WARNING: Some functions in this file are duplicated in string.ml for
efficiency reasons. When you modify the one in this file you need to
modify its duplicate in string.ml.
These functions have a "duplicated" comment above their definition.
*)externallength:bytes->int="%bytes_length"externalstring_length:string->int="%string_length"externalget:bytes->int->char="%bytes_safe_get"externalset:bytes->int->char->unit="%bytes_safe_set"externalcreate:int->bytes="caml_create_bytes"externalunsafe_get:bytes->int->char="%bytes_unsafe_get"externalunsafe_set:bytes->int->char->unit="%bytes_unsafe_set"externalunsafe_fill:bytes->int->int->char->unit="caml_fill_bytes"[@@noalloc]externalunsafe_to_string:bytes->string="%bytes_to_string"externalunsafe_of_string:string->bytes="%bytes_of_string"externalunsafe_blit:bytes->int->bytes->int->int->unit="caml_blit_bytes"[@@noalloc]externalunsafe_blit_string:string->int->bytes->int->int->unit="caml_blit_string"[@@noalloc]letmakenc=lets=createninunsafe_fills0nc;sletinitnf=lets=createninfori=0ton-1dounsafe_setsi(fi)done;sletempty=create0letcopys=letlen=lengthsinletr=createleninunsafe_blits0r0len;rletto_stringb=unsafe_to_string(copyb)letof_strings=copy(unsafe_of_strings)letsubsofslen=ifofs<0||len<0||ofs>lengths-lentheninvalid_arg"String.sub / Bytes.sub"elsebeginletr=createleninunsafe_blitsofsr0len;rendletsub_stringbofslen=unsafe_to_string(subbofslen)(* addition with an overflow check *)let(++)ab=letc=a+binmatcha<0,b<0,c<0with|true,true,false|false,false,true->invalid_arg"Bytes.extend"(* overflow *)|_->cletextendsleftright=letlen=lengths++left++rightinletr=createleninlet(srcoff,dstoff)=ifleft<0then-left,0else0,leftinletcpylen=Int.min(lengths-srcoff)(len-dstoff)inifcpylen>0thenunsafe_blitssrcoffrdstoffcpylen;rletfillsofslenc=ifofs<0||len<0||ofs>lengths-lentheninvalid_arg"String.fill / Bytes.fill"elseunsafe_fillsofslencletblits1ofs1s2ofs2len=iflen<0||ofs1<0||ofs1>lengths1-len||ofs2<0||ofs2>lengths2-lentheninvalid_arg"Bytes.blit"elseunsafe_blits1ofs1s2ofs2lenletblit_strings1ofs1s2ofs2len=iflen<0||ofs1<0||ofs1>string_lengths1-len||ofs2<0||ofs2>lengths2-lentheninvalid_arg"String.blit / Bytes.blit_string"elseunsafe_blit_strings1ofs1s2ofs2len(* duplicated in string.ml *)letiterfa=fori=0tolengtha-1dof(unsafe_getai)done(* duplicated in string.ml *)letiterifa=fori=0tolengtha-1dofi(unsafe_getai)doneletensure_ge(x:int)y=ifx>=ythenxelseinvalid_arg"Bytes.concat"letrecsum_lengthsaccseplen=function|[]->acc|hd::[]->lengthhd+acc|hd::tl->sum_lengths(ensure_ge(lengthhd+seplen+acc)acc)seplentlletrecunsafe_blitsdstpossepseplen=function[]->dst|hd::[]->unsafe_blithd0dstpos(lengthhd);dst|hd::tl->unsafe_blithd0dstpos(lengthhd);unsafe_blitsep0dst(pos+lengthhd)seplen;unsafe_blitsdst(pos+lengthhd+seplen)sepseplentlletconcatsep=function[]->empty|l->letseplen=lengthsepinunsafe_blits(create(sum_lengths0seplenl))0sepseplenlletcats1s2=letl1=lengths1inletl2=lengths2inletr=create(l1+l2)inunsafe_blits10r0l1;unsafe_blits20rl1l2;rexternalchar_code:char->int="%identity"externalchar_chr:int->char="%identity"letis_space=function|' '|'\012'|'\n'|'\r'|'\t'->true|_->falselettrims=letlen=lengthsinleti=ref0inwhile!i<len&&is_space(unsafe_gets!i)doincridone;letj=ref(len-1)inwhile!j>=!i&&is_space(unsafe_gets!j)dodecrjdone;if!j>=!ithensubs!i(!j-!i+1)elseemptyletescapeds=letn=ref0infori=0tolengths-1don:=!n+(matchunsafe_getsiwith|'\"'|'\\'|'\n'|'\t'|'\r'|'\b'->2|' '..'~'->1|_->4)done;if!n=lengthsthencopyselsebeginlets'=create!ninn:=0;fori=0tolengths-1dobeginmatchunsafe_getsiwith|('\"'|'\\')asc->unsafe_sets'!n'\\';incrn;unsafe_sets'!nc|'\n'->unsafe_sets'!n'\\';incrn;unsafe_sets'!n'n'|'\t'->unsafe_sets'!n'\\';incrn;unsafe_sets'!n't'|'\r'->unsafe_sets'!n'\\';incrn;unsafe_sets'!n'r'|'\b'->unsafe_sets'!n'\\';incrn;unsafe_sets'!n'b'|(' '..'~')asc->unsafe_sets'!nc|c->leta=char_codecinunsafe_sets'!n'\\';incrn;unsafe_sets'!n(char_chr(48+a/100));incrn;unsafe_sets'!n(char_chr(48+(a/10)mod10));incrn;unsafe_sets'!n(char_chr(48+amod10));end;incrndone;s'endletmapfs=letl=lengthsinifl=0thenselsebeginletr=createlinfori=0tol-1dounsafe_setri(f(unsafe_getsi))done;rendletmapifs=letl=lengthsinifl=0thenselsebeginletr=createlinfori=0tol-1dounsafe_setri(fi(unsafe_getsi))done;rendletfold_leftfxa=letr=refxinfori=0tolengtha-1dor:=f!r(unsafe_getai)done;!rletfold_rightfax=letr=refxinfori=lengtha-1downto0dor:=f(unsafe_getai)!rdone;!rletexistsps=letn=lengthsinletrecloopi=ifi=nthenfalseelseifp(unsafe_getsi)thentrueelseloop(succi)inloop0letfor_allps=letn=lengthsinletrecloopi=ifi=nthentrueelseifp(unsafe_getsi)thenloop(succi)elsefalseinloop0letuppercase_asciis=mapChar.uppercase_asciisletlowercase_asciis=mapChar.lowercase_asciisletapply1fs=iflengths=0thenselsebeginletr=copysinunsafe_setr0(f(unsafe_gets0));rendletcapitalize_asciis=apply1Char.uppercase_asciisletuncapitalize_asciis=apply1Char.lowercase_asciis(* duplicated in string.ml *)letstarts_with~prefixs=letlen_s=lengthsandlen_pre=lengthprefixinletrecauxi=ifi=len_prethentrueelseifunsafe_getsi<>unsafe_getprefixithenfalseelseaux(i+1)inlen_s>=len_pre&&aux0(* duplicated in string.ml *)letends_with~suffixs=letlen_s=lengthsandlen_suf=lengthsuffixinletdiff=len_s-len_sufinletrecauxi=ifi=len_sufthentrueelseifunsafe_gets(diff+i)<>unsafe_getsuffixithenfalseelseaux(i+1)indiff>=0&&aux0(* duplicated in string.ml *)letrecindex_recslimic=ifi>=limthenraiseNot_foundelseifunsafe_getsi=cthenielseindex_recslim(i+1)c(* duplicated in string.ml *)letindexsc=index_recs(lengths)0c(* duplicated in string.ml *)letrecindex_rec_optslimic=ifi>=limthenNoneelseifunsafe_getsi=cthenSomeielseindex_rec_optslim(i+1)c(* duplicated in string.ml *)letindex_optsc=index_rec_opts(lengths)0c(* duplicated in string.ml *)letindex_fromsic=letl=lengthsinifi<0||i>ltheninvalid_arg"String.index_from / Bytes.index_from"elseindex_recslic(* duplicated in string.ml *)letindex_from_optsic=letl=lengthsinifi<0||i>ltheninvalid_arg"String.index_from_opt / Bytes.index_from_opt"elseindex_rec_optslic(* duplicated in string.ml *)letrecrindex_recsic=ifi<0thenraiseNot_foundelseifunsafe_getsi=cthenielserindex_recs(i-1)c(* duplicated in string.ml *)letrindexsc=rindex_recs(lengths-1)c(* duplicated in string.ml *)letrindex_fromsic=ifi<-1||i>=lengthstheninvalid_arg"String.rindex_from / Bytes.rindex_from"elserindex_recsic(* duplicated in string.ml *)letrecrindex_rec_optsic=ifi<0thenNoneelseifunsafe_getsi=cthenSomeielserindex_rec_opts(i-1)c(* duplicated in string.ml *)letrindex_optsc=rindex_rec_opts(lengths-1)c(* duplicated in string.ml *)letrindex_from_optsic=ifi<-1||i>=lengthstheninvalid_arg"String.rindex_from_opt / Bytes.rindex_from_opt"elserindex_rec_optsic(* duplicated in string.ml *)letcontains_fromsic=letl=lengthsinifi<0||i>ltheninvalid_arg"String.contains_from / Bytes.contains_from"elsetryignore(index_recslic);truewithNot_found->false(* duplicated in string.ml *)letcontainssc=contains_froms0c(* duplicated in string.ml *)letrcontains_fromsic=ifi<0||i>=lengthstheninvalid_arg"String.rcontains_from / Bytes.rcontains_from"elsetryignore(rindex_recsic);truewithNot_found->falsetypet=bytesletcompare(x:t)(y:t)=Stdlib.comparexyexternalequal:t->t->bool="caml_bytes_equal"[@@noalloc](* duplicated in string.ml *)letsplit_on_charseps=letr=ref[]inletj=ref(lengths)infori=lengths-1downto0doifunsafe_getsi=septhenbeginr:=subs(i+1)(!j-i-1)::!r;j:=ienddone;subs0!j::!r(* Deprecated functions implemented via other deprecated functions *)[@@@ocaml.warning"-3"]letuppercases=mapChar.uppercasesletlowercases=mapChar.lowercasesletcapitalizes=apply1Char.uppercasesletuncapitalizes=apply1Char.lowercases(** {1 Iterators} *)letto_seqs=letrecauxi()=ifi=lengthsthenSeq.Nilelseletx=getsiinSeq.Cons(x,aux(i+1))inaux0letto_seqis=letrecauxi()=ifi=lengthsthenSeq.Nilelseletx=getsiinSeq.Cons((i,x),aux(i+1))inaux0letof_seqi=letn=ref0inletbuf=ref(make256'\000')inletresize()=(* resize *)letnew_len=Int.min(2*length!buf)Sys.max_string_lengthiniflength!buf=new_lenthenfailwith"Bytes.of_seq: cannot grow bytes";letnew_buf=makenew_len'\000'inblit!buf0new_buf0!n;buf:=new_bufinSeq.iter(func->if!n=length!bufthenresize();set!buf!nc;incrn)i;sub!buf0!n(** {6 Binary encoding/decoding of integers} *)(* The get_ functions are all duplicated in string.ml *)externalget_uint8:bytes->int->int="%bytes_safe_get"externalget_uint16_ne:bytes->int->int="%caml_bytes_get16"externalget_int32_ne:bytes->int->int32="%caml_bytes_get32"externalget_int64_ne:bytes->int->int64="%caml_bytes_get64"externalset_int8:bytes->int->int->unit="%bytes_safe_set"externalset_int16_ne:bytes->int->int->unit="%caml_bytes_set16"externalset_int32_ne:bytes->int->int32->unit="%caml_bytes_set32"externalset_int64_ne:bytes->int->int64->unit="%caml_bytes_set64"externalswap16:int->int="%bswap16"externalswap32:int32->int32="%bswap_int32"externalswap64:int64->int64="%bswap_int64"letget_int8bi=((get_uint8bi)lsl(Sys.int_size-8))asr(Sys.int_size-8)letget_uint16_lebi=ifSys.big_endianthenswap16(get_uint16_nebi)elseget_uint16_nebiletget_uint16_bebi=ifnotSys.big_endianthenswap16(get_uint16_nebi)elseget_uint16_nebiletget_int16_nebi=((get_uint16_nebi)lsl(Sys.int_size-16))asr(Sys.int_size-16)letget_int16_lebi=((get_uint16_lebi)lsl(Sys.int_size-16))asr(Sys.int_size-16)letget_int16_bebi=((get_uint16_bebi)lsl(Sys.int_size-16))asr(Sys.int_size-16)letget_int32_lebi=ifSys.big_endianthenswap32(get_int32_nebi)elseget_int32_nebiletget_int32_bebi=ifnotSys.big_endianthenswap32(get_int32_nebi)elseget_int32_nebiletget_int64_lebi=ifSys.big_endianthenswap64(get_int64_nebi)elseget_int64_nebiletget_int64_bebi=ifnotSys.big_endianthenswap64(get_int64_nebi)elseget_int64_nebiletset_int16_lebix=ifSys.big_endianthenset_int16_nebi(swap16x)elseset_int16_nebixletset_int16_bebix=ifnotSys.big_endianthenset_int16_nebi(swap16x)elseset_int16_nebixletset_int32_lebix=ifSys.big_endianthenset_int32_nebi(swap32x)elseset_int32_nebixletset_int32_bebix=ifnotSys.big_endianthenset_int32_nebi(swap32x)elseset_int32_nebixletset_int64_lebix=ifSys.big_endianthenset_int64_nebi(swap64x)elseset_int64_nebixletset_int64_bebix=ifnotSys.big_endianthenset_int64_nebi(swap64x)elseset_int64_nebixletset_uint8=set_int8letset_uint16_ne=set_int16_neletset_uint16_be=set_int16_beletset_uint16_le=set_int16_le