Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file zed_string.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524(*
* zed_string.ml
* -----------
* Copyright : (c) 2019, ZAN DoYe <zandoye@gmail.com>
* Licence : BSD3
*
* This file is a part of Zed, an editor engine.
*)(* This aliasing needs to come before 'open Result' which now offers a
'compare' function. We don't use 'Pervasives.compare' or 'Stdlib.compare'
because neither seems to work with every version of OCaml. *)letpervasives_compare=compareopenResultexceptionInvalidofstring*stringexceptionOut_of_bounds(** Exception raised when trying to access a character which is
outside the bounds of a string. *)letfailstrposmsg=raise(Invalid(Printf.sprintf"at position %d: %s"posmsg,str))moduleZed_string0=structtypeseg_width={start:int;len:int;width:int;}typeall_width={len:int;width:int;}typewidth=(all_width,seg_width)resulttypet=Zed_utf8.tletaval_width=function|Ok{len=_;width}->width|Error{start=_;len=_;width}->widthletbytesstr=String.lengthstrletsizestr=Zed_utf8.lengthstrletcopyt=tletunsafe_nextstrofs=letstr_len=String.lengthstrinletrecskipstrofs=ifofs>=str_lenthenstr_lenelseletchr,next=Zed_utf8.unsafe_extract_nextstrofsinifZed_char.is_combining_markchrthenskipstrnextelseofsinifofs<0||ofs>=String.lengthstrthenraiseOut_of_boundselseletchr,next=Zed_utf8.unsafe_extract_nextstrofsinifZed_char.is_printablechrthenskipstrnextelsenextletnext_ofsstrofs=letstr_len=String.lengthstrinletrecskipstrofs=ifofs>=str_lenthenstr_lenelseletchr,next=Zed_utf8.unsafe_extract_nextstrofsinifZed_char.is_combining_markchrthenskipstrnextelseofsinifofs<0||ofs>=String.lengthstrthenraiseOut_of_boundselseletchr,next=Zed_utf8.unsafe_extract_nextstrofsinifZed_char.is_printable_corechrthenskipstrnextelseifZed_char.is_combining_markchrthenfailstrofs"individual combining marks encountered"elsenextletlengthstr=leteos=String.lengthstrinletreclengthlenofs=ifofs<eosthenlength(len+1)(unsafe_nextstrofs)elseleninlength00letunsafe_prevstrofs=letrecskipstrofs=ifofs=0thenofselseletchr,prev=Zed_utf8.unsafe_extract_prevstrofsinifZed_char.is_combining_markchrthenskipstrprevelseprevinifofs<=0||ofs>String.lengthstrthenraiseOut_of_boundselseletchr,prev=Zed_utf8.extract_prevstrofsinifZed_char.is_combining_markchrthenskipstrprevelseprevletprev_ofsstrofs=letrecskipstrofs=ifofs=0thenofselseletchr,prev=Zed_utf8.unsafe_extract_prevstrofsinifZed_char.is_combining_markchrthenskipstrprevelseprevinifofs<=0||ofs>String.lengthstrthenraiseOut_of_boundselseletchr,prev=Zed_utf8.extract_prevstrofsinifZed_char.is_combining_markchrthenletprev=skipstrprevinifprev=0thenifZed_char.is_printable_core(Zed_utf8.unsafe_extractstr0)thenprevelsefailstr0"individual combining marks encountered"elseletchr,next=Zed_utf8.unsafe_extract_nextstrprevinmatchZed_char.prop_uCharchrwith|Printable0|Other|Null->failstrnext"individual combining marks encountered"|_->prevelseprevletrecmove_lstrofslen=iflen=0thenofselseifofs>=String.lengthstrthenraiseOut_of_boundselsemove_lstr(unsafe_nextstrofs)(len-1)letmove_bstrofslen=letrecmovestrofslen=iflen=0thenofselseifofs<0thenraiseOut_of_boundselsemovestr(unsafe_prevstrofs)(len-1)inifofs<0||ofs>String.lengthstrthenraiseOut_of_boundselsemovestrofslenletrecmove_l_rawstrofslen=iflen=0thenofselseifofs>=String.lengthstrthenraiseOut_of_boundselsemove_l_rawstr(Zed_utf8.unsafe_nextstrofs)(len-1)letmove_b_rawstrofslen=letrecmovestrofslen=iflen=0thenofselseifofs<0thenraiseOut_of_boundselsemovestr(Zed_utf8.unsafe_prevstrofs)(len-1)inifofs<0||ofs>String.lengthstrthenraiseOut_of_boundselsemovestrofslenletextractstrofs=letnext=next_ofsstrofsinZed_char.unsafe_of_utf8(String.substrofs(next-ofs))letextract_nextstrofs=letnext=next_ofsstrofsin(Zed_char.unsafe_of_utf8(String.substrofs(next-ofs)),next)letextract_prevstrofs=letprev=prev_ofsstrofsin(Zed_char.unsafe_of_utf8(String.substrprev(ofs-prev)),prev)letto_raw_liststr=Zed_utf8.explodestrletto_raw_arraystr=Array.of_list(to_raw_liststr)typeindex=intletgetstridx=ifidx<0thenraiseOut_of_boundselseextractstr(move_lstr0idx)letget_raw=Zed_utf8.getletempty()=""letwidth_ofs?(start=0)?numstr=letstr_len=String.lengthstrinletreccalcwidxofs=ifofs<str_lenthenletchr,next=extract_nextstrofsinletchr_width=Zed_char.widthchrinifchr_width>0thencalc(w+chr_width)(idx+1)nextelseError{start;len=idx-start;width=w}elseOk{len=idx-start;width=w}inletcalc_numnumwidxofs=letreccalcnwidxofs=ifofs<str_len&&n>0thenletchr,next=extract_nextstrofsinletchr_width=Zed_char.widthchrinifchr_width>0thencalc(n-1)(w+chr_width)(idx+1)nextelseError{start;len=idx-start;width=w}elseOk{len=idx-start;width=w}incalcnumwidxofsinmatchnumwith|Somenum->calc_numnum0startstart|None->calc0startstartletwidth?(start=0)?numstr=letofs=move_lstr0startinwidth_ofs~start:ofs?numstrletexplodestr=letstr_len=String.lengthstrinletrecauxaccstrofs=ifofs>0thenletchr,prev=extract_prevstrofsinaux(chr::acc)strprevelseaccinifstr_len>0thenaux[]strstr_lenelse[]letrev_explodestr=letstr_len=String.lengthstrinletrecauxaccofs=ifofs<str_lenthenletchr,next=extract_nextstrofsinaux(chr::acc)nextelse[]inifstr_len>0thenaux[]0else[]letunsafe_explodestr=letstr_len=String.lengthstrinletrecauxaccstrofs=ifofs>0thenletchr,prev=extract_prevstrofsinaux(chr::acc)strprevelseaccinifstr_len>0thenaux[]strstr_lenelse[]letunsafe_rev_explodestr=letstr_len=String.lengthstrinletrecauxaccofs=ifofs<str_lenthenletchr,next=extract_nextstrofsinaux(chr::acc)nextelse[]inifstr_len>0thenaux[]0else[]letimplodechars=String.concat""(List.mapZed_char.to_utf8chars)letinitlen(f:int->Zed_char.t)=letreccreateaccn=ifn>0thencreate((f(n-1))::acc)(n-1)elseaccinimplode(create[]len)letinit_from_uCharslenf=matchlenwith|0->empty()|lenwhenlen>0->letreccreateaccn=ifn>0thencreate((f(n-1))::acc)(n-1)elseaccinletuChars=create[]leninletzChars,_=Zed_char.zChars_of_uCharsuCharsinimplodezChars|_->raise(Invalid_argument"Zed_string0.init_from_uChars")letunsafe_of_uCharsuChars=matchuCharswith|[]->""|_->String.concat""(List.mapZed_utf8.singletonuChars)letof_uCharsuChars=matchuCharswith|[]->"",[]|fst::_->ifZed_char.is_combining_markfstthen("",uChars)else(uChars|>List.mapZed_utf8.singleton|>String.concat"",[])letunsafe_appends1s2=s1^s2letappends1s2=letvalidate_s2()=lets2_first=Zed_utf8.unsafe_extracts20inifZed_char.is_combining_marks2_firstthenfails20"individual combining marks encountered"elses2inifs1=""thenvalidate_s2()elseifs2=""thens1elselet(s1_last,_)=extract_prevs1(bytess1)inifZed_char.(is_printable_core(cores1_last))thenunsafe_appends1s2elseunsafe_appends1(validate_s2())externalid:'a->'a="%identity"letunsafe_of_utf8:string->t=idletof_utf8:string->t=funstr->ifString.lengthstr=0then""elseifZed_char.is_combining_mark(Zed_utf8.extractstr0)thenfailstr0"individual combining marks encountered"elseunsafe_of_utf8strletto_utf8:t->string=idletfor_allpstr=List.for_allp(explodestr)letcheck_rangetn=n>=0&&n<=lengthtletlookstrofs=Zed_utf8.extractstrofsletnthtn=ifcheck_rangetnthennelseraise(Invalid_argument"Zed_string.nth")letnexttn=letn=n+1inifcheck_rangetnthennelseraise(Invalid_argument"Zed_string.next")letprevtn=letn=n-1inifcheck_rangetnthennelseraise(Invalid_argument"Zed_string.prev")letout_of_rangetn=n<0||n>=lengthtletiterfstr=List.iterf(explodestr)letrev_iterfstr=List.iterf(rev_explodestr)letfoldfstracc=letrecauxfcharsacc=matchcharswith|[]->acc|chr::tl->auxftl(fchracc)inauxf(explodestr)accletrev_foldfstracc=letrecauxfcharsacc=matchcharswith|[]->acc|chr::tl->auxftl(fchracc)inauxf(rev_explodestr)accletmapfstr=implode(List.mapf(explodestr))letrev_mapfstr=implode(List.mapf(rev_explodestr))letcomparestr1str2=Zed_utils.list_compare~compare:Zed_char.compare_raw(explodestr1)(explodestr2)letfirst(_:t)=0letlastt=max(lengtht-1)0letmovetin=ifn>=0thenmove_ltinelsemove_btinletmove_rawtin=ifn>=0thenmove_l_rawtinelsemove_b_rawtinletcompare_index(_:t)ij=pervasives_compareijletsub_ofs~ofs~lens=ifofs<0||len<0||ofs>bytess-lentheninvalid_arg"Zed_string.sub"elseString.subsofslenletsub~pos~lens=ifpos<0||len<0||pos>lengths-lentheninvalid_arg"Zed_string.sub"elseletofs_start=move_ls0posinletofs_end=move_lsofs_startleninString.subsofs_start(ofs_end-ofs_start)letaftersi=letlen=lengthsinifi<lenthensub~pos:i~len:(len-i)selseempty()letrecunsafe_sub_equalstrofssubofs_sub=ifofs_sub=String.lengthsubthentrueelse(String.unsafe_getstrofs=String.unsafe_getsubofs_sub)&&unsafe_sub_equalstr(ofs+1)sub(ofs_sub+1)letstarts_with~prefixstr=ifString.lengthprefix>String.lengthstrthenfalseelseunsafe_sub_equalstr0prefix0letmakelenc=implode(Array.to_list(Array.makelenc))letends_with~suffixstr=Zed_utf8.ends_withstrsuffixmoduleBuf0=structtypebuf=Buffer.tletcreaten=Buffer.createnletcontentsb=Buffer.contentsbletclearb=Buffer.clearbletresetb=Buffer.resetbletlengthb=length(contentsb)letadd_zCharbzChar=Buffer.add_stringb(Zed_char.to_utf8zChar)letadd_uCharbuChar=Buffer.add_stringb(Zed_utf8.singletonuChar)letadd_stringbs=Buffer.add_stringbsletadd_bufferb1b2=Buffer.add_bufferb1b2endendincludeZed_string0moduleBuf=Buf0