123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161(***********************************************************************)(* *)(* Objective Caml *)(* *)(* François Pessaux, projet Cristal, INRIA Rocquencourt *)(* Pierre Weis, projet Cristal, INRIA Rocquencourt *)(* Jun Furuse, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1999-2004, *)(* Institut National de Recherche en Informatique et en Automatique. *)(* Distributed only by permission. *)(* *)(***********************************************************************)(* $Id: mstring.ml,v 1.1 2006/11/28 15:43:28 rousse Exp $*)(** String utilities *)openUtil(** split a string according to char_sep predicate *)letsplit_strchar_sepstr=letlen=String.lengthstriniflen=0then[]elseletrecskip_sepcur=ifcur>=lenthencurelseifchar_sepstr.[cur]thenskip_sep(succcur)elsecurinletrecsplitbegcur=ifcur>=lenthenifbeg=curthen[]else[String.substrbeg(len-beg)]elseifchar_sepstr.[cur]thenletnextw=skip_sepcurinString.substrbeg(cur-beg)::splitnextwnextwelsesplitbeg(succcur)inletwstart=skip_sep0insplitwstartwstart(* split a string according to char_sep predicate *)letsplit_str_quotedchar_sepstr=letlen=String.lengthstriniflen=0then[]elseletcword=ref""inletrecskip_sepcur=ifcur>=lenthencurelseifchar_sepstr.[cur]thenskip_sep(succcur)elsecurinletrecclose_quotecur=ifcur>=lenthencurelseifstr.[cur]='"'thencurelsebegincword:=!cword^String.make1str.[cur];close_quote(succcur)endinletrecsplitbegcur=ifcur>=lenthenifbeg=curthen[]else[!cword]elseifstr.[cur]='"'thenletendquote=close_quote(succcur)insplitbeg(succendquote)elseifchar_sepstr.[cur]thenletnextw=skip_sepcurinletword=!cwordincword:="";word::splitnextwnextwelsebegincword:=!cword^String.make1str.[cur];splitbeg(succcur)endinletwstart=skip_sep0insplitwstartwstart(* extract the . suffix (dot excluded) of a string *)letget_suffixs=tryletdotpos=succ(String.rindexs'.')inString.subsdotpos(String.lengths-dotpos)with|Not_found->""(* HEX/DEC conversions *)lethex_to_decc=matchcwith|'0'..'9'->int_of_charc-48|'a'..'f'->int_of_charc-87(* 87 = int_of_char 'a' - 10 *)|'A'..'F'->int_of_charc-55(* 55 = int_of_char 'A' - 10 *)|_->failwith"hex_to_dec"letdec_to_hexi=ifi<10thenchar_of_int(i+48)(* 48 = int_of_char '0' *)elsechar_of_int(i+55)(* 55 = int_of_char 'A' - 10 *)(* Converting a hex stored string *)lethex_to_strings=letlen=String.lengths/2inString.initlen@@funi->char_of_int(16*(hex_to_decs.[i+i])+hex_to_decs.[i+i+1])letgensym=letcnter=ref0in(funn->incrcnter;n^string_of_int!cnter)letrem_trailing_sps=letl=String.lengthsinletpos=ref(l-1)inwhile!pos>=0&&List.mems.[!pos][' ';'\t']dodecrposdone;if!pos=l-1thenselseString.subs0(succ!pos)letcatenate_sep=String.concat(** Filters CRLF:
- CR -> LF
- CRLF -> LF
- LF -> LF
We do this on successive chunks of a stream, so we need to consider
the case when the chunk finishes on CR.
Assume len > 0
*)letnorm_crlflastwascrbufoffslen=letrpos=refoffsandwpos=ref0anddest=Bytes.create(len+1)(* we need one more char *)andlimit=offs+len-1andlastiscr=reffalseiniflastwascrthenifbuf.[!rpos]='\n'thenbegindest<<!wpos&'\n';incrrpos;incrwposendelsebegindest<<!wpos&'\n';incrwposend;while!rpos<limitdomatchbuf.[!rpos]with|'\n'->dest<<!wpos&'\n';incrrpos;incrwpos|'\r'->ifbuf.[!rpos+1]='\n'thenbegindest<<!wpos&'\n';rpos:=!rpos+2;incrwposendelsebegindest<<!wpos&'\n';incrrpos;incrwposend|c->dest<<!wpos&c;incrrpos;incrwposdone;beginmatchbuf.[offs+len-1]with|'\n'->dest<<!wpos&'\n';incrwpos|'\r'->lastiscr:=true|c->dest<<!wpos&c;incrwposend;Bytes.sub_stringdest0!wpos,!lastiscrlethexcharc=leti=int_of_charcinString.init3@@function|0->'%'|1->dec_to_hex(i/16)|2->dec_to_hex(imod16)|_->assertfalse