123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303(*
* ExtString - Additional functions for string manipulations.
* Copyright (C) 2003 Nicolas Cannasse
*
* This library 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.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)exceptionInvalid_stringmoduleString=structincludeString#ifOCAML<413letempty =""#endifletstarts_withstr~prefix:p=iflengthstr<lengthpthenfalseelseletrecloopstrpi=ifi=lengthpthentrueelseifunsafe_getstri<>unsafe_getpithenfalseelseloopstrp(i+1)inloopstrp0letends_withs~suffix:e=iflengths<lengthethenfalseelseletrecloopsei=ifi=lengthethentrueelseifunsafe_gets(lengths-lengthe+i)<>unsafe_geteithenfalseelseloopse(i+1)inloopse0letfind_fromstrpossub=letsublen=lengthsubinifsublen=0then0elseletfound=ref0inletlen=lengthstrintryfori=postolen-sublendoletj=ref0inwhileunsafe_getstr(i+!j)=unsafe_getsub!jdoincrj;if!j=sublenthenbeginfound:=i;raiseExit;end;done;done;raiseInvalid_stringwithExit->!foundletfindstrsub=find_from str0sublet existsstr~sub=tryignore(findstrsub);truewithInvalid_string->falseletstrip?(chars=" \t\r\n")s=letp=ref0inlet l=lengthsinwhile!p<l&&containschars(unsafe_gets!p)doincrp;done;letp=!pinletl=ref(l-1)inwhile!l>=p&&containschars(unsafe_gets!l)dodecrl;done;subsp(!l-p+1)letsplitstrsep=letp=findstrsepinletlen=lengthsepinletslen=lengthstrinsubstr0p,substr(p+len)(slen-p-len)letnsplit strsep=ifstr=""then[]elseifsep=""thenraiseInvalid_stringelseletrecloopaccpos=ifpos>String.lengthstrthenList.revaccelseleti=tryfind_fromstrpossepwithInvalid_string->String.lengthstrinloop(String.substrpos(i-pos)::acc)(i+String.lengthsep)inloop[]0let join=concatletslice=letclipmaxx=ifx>maxthenmaxelseifx<0then0elsexinfun?(first=0)?(last=Sys.max_string_length)s->letlen=String.lengthsinleti=iffirst=0then0elsecliplen(iffirst<0thenlen+firstelsefirst)inletj=iflast=Sys.max_string_lengththenlenelsecliplen(iflast<0thenlen+lastelselast)inifi>=j||i=lenthenmake0' 'elsesubsi(j-i)letlchops=ifs=""then""elsesubs1(lengths-1)letrchops=ifs=""then""elsesubs0(lengths-1)letof_int=string_of_intletof_float=string_of_floatletof_char =make1letto_ints=tryint_of_stringswith_->raiseInvalid_stringletto_floats=tryfloat_of_stringswith_->raiseInvalid_stringletenums=letl=lengthsinletrecmakei=Enum.make~next:(fun()->if!i=lthenraiseEnum.No_more_elementselseletp=!iinincri;unsafe_getsp)~count:(fun()->l-!i)~clone:(fun()->make(ref!i))inmake(ref0)letof_enume=letl=Enum.counteinlets=Bytes.createlinleti=ref0inEnum.iter(func-> Bytes.unsafe_sets!ic;incri)e;(* 's' doesn't escape and will never be mutated again *)Bytes.unsafe_to_stringsletfold_left=letrecloopstrfinresult=ifi=nthenresultelseloopstrf(i+1)n(fresult(String.unsafe_getstri))infunfinitstr->loop strf0(String.lengthstr)initletfold_right =letrecloopstrfiresult=ifi=0thenresultelseleti'=i-1inloopstrfi'(f(String.unsafe_getstri')result)infunfstrinit->loopstrf(String.lengthstr)init(* explode and implode from the OCaml Expert FAQ. *)letexplodes=letrecexpil=ifi<0thenlelseexp(i-1)(s.[i]::l)inexp(String.lengths-1)[]letimplodel=letres=Bytes.create(List.lengthl)inletrecimpi=function|[]->res|c::l->Bytes.setresic;imp(i+1)linlets=imp0lin(*'s' doesn't escape and will never be mutated again *)Bytes.unsafe_to_stringsletreplace_charsfs=letlen=String.lengthsinlettlen=ref0inlet recloopiacc=ifi=lenthenaccelselets=f(unsafe_getsi)intlen:=!tlen+lengths;loop(i+1)(s::acc)inletstrs=loop0[]inletsbuf=Bytes.create!tleninletpos=ref!tleninletrecloop2=function|[]->()|s::acc->letlen=lengthsinpos:=!pos-len;blit s0sbuf!poslen;loop2 accinloop2 strs;(* 'sbuf' doesn't escape and will never be mutated again *)Bytes.unsafe_to_stringsbufletreplace ~str~sub ~by=tryleti=findstrsubin(true,(slice~last:istr)^by^(slice~first:(i+(String.lengthsub))str))withInvalid_string->(false,String.substr0(String.lengthstr))#ifOCAML<403letuppercase_ascii=uppercaseletlowercase_ascii=lowercaseletcapitalize_ascii=capitalizelet uncapitalize_ascii=uncapitalizeletequal=(=)#endif#ifOCAML<404letsplit_on_charseps=letr=ref []inletj=ref (lengths)infori=lengths-1downto0doifunsafe_getsi=septhenbeginr:=subs(i+1)(!j-i-1)::!r;j:=ienddone;subs0!j::!r#endif#ifOCAML<405letrecindex_rec_optslimic=ifi>=limthenNoneelseifunsafe_getsi=cthenSomeielseindex_rec_optslim(i+1)cletindex_optsc=index_rec_opts(lengths)0cletindex_from_optsic=letl=lengthsinifi<0||i>ltheninvalid_arg"ExtString.index_from_opt"elseindex_rec_optslicletrecrindex_rec_optsic=ifi<0thenNoneelseifunsafe_getsi=cthenSomeielserindex_rec_opts(i-1)cletrindex_optsc=rindex_rec_opts(lengths-1)cletrindex_from_optsic=ifi<-1||i>=lengthstheninvalid_arg"ExtString.rindex_from_opt"elserindex_rec_optsic#endif#ifOCAML>=500letcreate=Bytes.createletset=Bytes.setletunsafe_set=Bytes.unsafe_setletcopyx=Bytes.unsafe_to_string(Bytes.copy(Bytes.unsafe_of_stringx))letfill=Bytes.fillletunsafe_fill=Bytes.unsafe_fillletuppercase=uppercase_asciiletlowercase=lowercase_asciiletcapitalize=capitalize_asciiletuncapitalize=uncapitalize_ascii#endifend