123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865# 1 "Camomile/public/uCol.ml"(** Unicode collation algorithm *)(* Copyright (C) 2002, 2003 Yamagata Yoriyuki *)(* 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 of *)(* the License, or (at your option) any later version. *)(* As a special exception to the GNU Library General Public License, you *)(* may link, statically or dynamically, a "work that uses this library" *)(* with a publicly distributed version of this library to produce an *)(* executable file containing portions of this library, and distribute *)(* that executable file under terms of your choice, without any of the *)(* additional requirements listed in clause 6 of the GNU Library General *)(* Public License. By "a publicly distributed version of this library", *)(* we mean either the unmodified Library as distributed by the authors, *)(* or a modified version of this library that is distributed under the *)(* conditions defined in clause 3 of the GNU Library General Public *)(* License. This exception does not however invalidate any other reasons *)(* why the executable file might be covered by the GNU Library General *)(* Public 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 *)(* You can contact the authour by sending email to *)(* yoriyuki.y@gmail.com *)typevariable_option=[`Blanked|`Non_ignorable|`Shifted|`Shift_Trimmed]typeprecision=[`Primary|`Secondary|`Tertiary|`Quaternary]moduletypeType=sigtypetexttypeindex(** For locale, see {!Locale}.
If [locale] is omitted, the standard UCA order is used.
If [prec] is omitted, the maximum possible strength is used.
If [variable] is omitted, the default of the locale
(usually [`Shifted]) is used.
The meaning of the returned value is similar to Pervasives.compare *)valcompare:?locale:string->?prec:precision->?variable:variable_option->text->text->int(** Binary comparison of sort_key gives the same result as [compare].
i.e.
[compare t1 t2 = Pervasives.compare (sort_key t1) (sort_key t2)]
If the same texts are repeatedly compared,
pre-computation of sort_key gives better performance. *)valsort_key:?locale:string->?prec:precision->?variable:variable_option->text->string(** Comparison with the sort key. *)valcompare_with_key:?locale:string->?prec:precision->?variable:variable_option->string->text->intvalsearch_with_key:?locale:string->?prec:precision->?variable:variable_option->string->text->index->(index*index)valsearch:?locale:string->?prec:precision->?variable:variable_option->text->text->index->(index*index)endmoduleMake(Config:ConfigInt.Type)(Text:UnicodeString.Type)=structmoduleUnidata=Unidata.Make(Config)moduleUCharInfo=UCharInfo.Make(Config)letlogical_order_exception_tbl=UCharInfo.load_property_tbl`Logical_Order_Exceptionletis_logical_order_exceptionu=UCharTbl.Bool.getlogical_order_exception_tbluletrecrearrange_auxxpos=ifpos>XString.lengthx-2then()elseletu=XString.getxposinifis_logical_order_exceptionuthenbeginXString.setxpos(XString.getx(pos+1));XString.setx(pos+1)u;rearrange_auxx(pos+2)endelserearrange_auxx(pos+1)letrearrangex=rearrange_auxx0letremove_ignorablece_tblx=letrecloop0i=ifXString.lengthx<=ithen()elseletu=XString.getxiinmatchUnidata.cece_tbluwith[([],[ce])]whence=Unidata.complete_ignorable->loop1(i+1)i|_->loop0(i+1)andloop1ik=(*k < i *)ifXString.lengthx<=ithenbeginXString.shrinkxk;endelseletu=XString.getxiinmatchUnidata.cece_tbluwith[([],[ce])]whence=Unidata.complete_ignorable->loop1(i+1)k|_->XString.setxku;loop1(i+1)(k+1)inloop00letnoncharacter_code_point_tbl=UCharInfo.load_property_tbl`Noncharacter_Code_Pointletis_noncharacter_code_pointu=UCharTbl.Bool.getnoncharacter_code_point_tbluletreverses=ifBytes.lengths=0then()elseletlast=Bytes.lengths-1infori=0tolast/2doletc=Bytes.getsiinBytes.setsi(Bytes.gets(last-i));Bytes.sets(last-i)cdoneletshiftrightxij=fork=jdowntoidoXString.setx(k+1)(XString.getxk)doneletrecremove_charsxi=function[]->i|j::rest->shiftrightxi(j-1);remove_charsx(i+1)restlettrimstart_regularkey=letrecloopi=ifi>0&&(Char.codekey.[i-1])lsl8lor(Char.codekey.[i])>start_regularthenloop(i-2)elseString.subkey0(i+1)inloop(String.lengthkey-1)letis_variablevariable_topce=Unidata.primaryce<>0&&Unidata.primaryce<=variable_topletis_ignorablece=Unidata.primaryce=0letadd_i16bufn=Buffer.add_charbuf(Char.unsafe_chr(nlsr8));Buffer.add_charbuf(Char.unsafe_chr(nland255))letadd_bytebufn=Buffer.add_charbuf(Char.unsafe_chrn)typenon_ignorable_keybuf={non_ignorable_col_info:Unidata.col_info;non_ignorable_prec:precision;non_ignorable_primary:Buffer.t;non_ignorable_secondary:Buffer.t;non_ignorable_tertiary:Buffer.t;non_ignorable_quaternary:Buffer.t;mutablenon_ignorable_count:int}letaddce_non_ignorablekeybufce=letw1=Unidata.primaryceinifw1<>0&&w1<>keybuf.non_ignorable_col_info.hiraganaQ_weightthenadd_i16keybuf.non_ignorable_primaryw1;matchkeybuf.non_ignorable_precwith`Primary->()|_->letw2=Unidata.secondaryceinifw2<>0thenadd_bytekeybuf.non_ignorable_secondaryw2;matchkeybuf.non_ignorable_precwith`Secondary->()|_->letw3=Unidata.tertiaryceinifw3<>0thenadd_bytekeybuf.non_ignorable_tertiaryw3;matchkeybuf.non_ignorable_precwith`Tertiary->()|_->ifnotkeybuf.non_ignorable_col_info.hiraganaQthen()elseifw1=keybuf.non_ignorable_col_info.hiraganaQ_weightthenbeginifkeybuf.non_ignorable_count>0thenbeginadd_i16keybuf.non_ignorable_quaternary(1+keybuf.non_ignorable_count);keybuf.non_ignorable_count<-0;end;add_i16keybuf.non_ignorable_quaternary1;endelsebeginkeybuf.non_ignorable_count<-keybuf.non_ignorable_count+1;ifkeybuf.non_ignorable_count=0xffff-1thenbeginadd_i16keybuf.non_ignorable_quaternary0xffff;keybuf.non_ignorable_count<-0;endendletterminate_non_ignorablekeybuf=letc=keybuf.non_ignorable_countinifc>0thenadd_i16keybuf.non_ignorable_quaternary(1+c)typeblanked_keybuf={blanked_col_info:Unidata.col_info;blanked_prec:precision;blanked_primary:Buffer.t;blanked_secondary:Buffer.t;blanked_tertiary:Buffer.t;blanked_quaternary:Buffer.t;mutableblanked_after_variable:bool;mutableblanked_count:int}letaddce_blankedkeybufce=ifis_ignorablece&&keybuf.blanked_after_variablethen()elseifis_variablekeybuf.blanked_col_info.variable_topcethenkeybuf.blanked_after_variable<-trueelsebeginkeybuf.blanked_after_variable<-false;letw1=Unidata.primaryceinifw1<>0&&w1<>keybuf.blanked_col_info.hiraganaQ_weightthenadd_i16keybuf.blanked_primaryw1;matchkeybuf.blanked_precwith`Primary->()|_->letw2=Unidata.secondaryceinifw2<>0thenadd_bytekeybuf.blanked_secondaryw2;matchkeybuf.blanked_precwith`Secondary->()|_->letw3=Unidata.tertiaryceinifw3<>0thenadd_bytekeybuf.blanked_tertiaryw3;matchkeybuf.blanked_precwith`Tertiary->()|_->ifnotkeybuf.blanked_col_info.hiraganaQthen()elseifw1=keybuf.blanked_col_info.hiraganaQ_weightthenbeginifkeybuf.blanked_count>0thenbeginadd_i16keybuf.blanked_quaternary(1+keybuf.blanked_count);keybuf.blanked_count<-0end;add_i16keybuf.blanked_quaternary1;endelsebeginkeybuf.blanked_count<-keybuf.blanked_count+1;ifkeybuf.blanked_count=0xffff-1thenbeginadd_i16keybuf.blanked_quaternary0xffff;keybuf.blanked_count<-0endendendletterminate_blankedkeybuf=letc=keybuf.blanked_countinifc>0thenadd_i16keybuf.blanked_quaternary(1+c)typeshifted_keybuf={shifted_col_info:Unidata.col_info;shifted_prec:precision;shifted_primary:Buffer.t;shifted_secondary:Buffer.t;shifted_tertiary:Buffer.t;shifted_quaternary:Buffer.t;mutableshifted_after_variable:bool;mutableshifted_count:int}letstart_regularkeybuf=ifkeybuf.shifted_col_info.hiraganaQthenkeybuf.shifted_col_info.hiraganaQ_weightelsekeybuf.shifted_col_info.variable_topletaddce_shiftedkeybufce=letstart_regular=start_regularkeybufinifis_ignorablece&&keybuf.shifted_after_variablethen()elseifis_variablekeybuf.shifted_col_info.variable_topcethenbeginkeybuf.shifted_after_variable<-true;matchkeybuf.shifted_precwith`Quaternary->ifkeybuf.shifted_count>0thenbeginadd_i16keybuf.shifted_quaternary(start_regular+keybuf.shifted_count);keybuf.shifted_count<-0end;add_i16keybuf.shifted_quaternary(Unidata.primaryce);|_->()endelsebeginkeybuf.shifted_after_variable<-false;letw1=Unidata.primaryceinifw1<>0&&w1<>keybuf.shifted_col_info.hiraganaQ_weightthenadd_i16keybuf.shifted_primaryw1;matchkeybuf.shifted_precwith`Primary->()|_->letw2=Unidata.secondaryceinifw2<>0thenadd_bytekeybuf.shifted_secondaryw2;matchkeybuf.shifted_precwith`Secondary->()|_->letw3=Unidata.tertiaryceinifw3<>0thenadd_bytekeybuf.shifted_tertiaryw3;matchkeybuf.shifted_precwith`Tertiary->()|_->ifis_ignorablecethen()elseifw1=keybuf.shifted_col_info.hiraganaQ_weight&&keybuf.shifted_col_info.hiraganaQthenbeginifkeybuf.shifted_count>0thenbeginadd_i16keybuf.shifted_quaternary(start_regular+keybuf.shifted_count);keybuf.shifted_count<-0end;add_i16keybuf.shifted_quaternaryw1endelsebeginkeybuf.shifted_count<-keybuf.shifted_count+1;ifkeybuf.shifted_count=0xffff-start_regularthenbeginadd_i16keybuf.shifted_quaternary0xffff;keybuf.shifted_count<-0endendendletterminate_shiftedkeybuf=letc=keybuf.shifted_countinifc>0thenadd_i16keybuf.shifted_quaternary((start_regularkeybuf)+c)letterminate_shift_trimmedkeybuf=letk4=Buffer.contentskeybuf.shifted_quaternaryinletk4=trim(start_regularkeybuf)k4inBuffer.clearkeybuf.shifted_quaternary;Buffer.add_stringkeybuf.shifted_quaternaryk4typekeybuf=Non_ignorableofnon_ignorable_keybuf|Blankedofblanked_keybuf|Shiftedofshifted_keybuf|Shift_Trimmedofshifted_keybufletcreate_keybufpreccol_info=matchcol_info.Unidata.variable_optionwith`Non_ignorable->Non_ignorable{non_ignorable_col_info=col_info;non_ignorable_prec=prec;non_ignorable_primary=Buffer.create0;non_ignorable_secondary=Buffer.create0;non_ignorable_tertiary=Buffer.create0;non_ignorable_quaternary=Buffer.create0;non_ignorable_count=0}|`Blanked->Blanked{blanked_col_info=col_info;blanked_prec=prec;blanked_primary=Buffer.create0;blanked_secondary=Buffer.create0;blanked_tertiary=Buffer.create0;blanked_quaternary=Buffer.create0;blanked_after_variable=false;blanked_count=0}|`Shifted->Shifted{shifted_col_info=col_info;shifted_prec=prec;shifted_primary=Buffer.create0;shifted_secondary=Buffer.create0;shifted_tertiary=Buffer.create0;shifted_quaternary=Buffer.create0;shifted_after_variable=false;shifted_count=0}|`Shift_Trimmed->Shift_Trimmed{shifted_col_info=col_info;shifted_prec=prec;shifted_primary=Buffer.create0;shifted_secondary=Buffer.create0;shifted_tertiary=Buffer.create0;shifted_quaternary=Buffer.create0;shifted_after_variable=false;shifted_count=0}letcol_info_of_keybuf=functionNon_ignorableb->b.non_ignorable_col_info|Blankedb->b.blanked_col_info|Shiftedb|Shift_Trimmedb->b.shifted_col_infoletprecision_of_keybuf=functionNon_ignorableb->b.non_ignorable_prec|Blankedb->b.blanked_prec|Shiftedb|Shift_Trimmedb->b.shifted_precletprimary_of_keybuf=functionNon_ignorableb->b.non_ignorable_primary|Blankedb->b.blanked_primary|Shiftedb|Shift_Trimmedb->b.shifted_primaryletsecondary_of_keybuf=functionNon_ignorableb->b.non_ignorable_secondary|Blankedb->b.blanked_secondary|Shiftedb|Shift_Trimmedb->b.shifted_secondarylettertiary_of_keybuf=functionNon_ignorableb->b.non_ignorable_tertiary|Blankedb->b.blanked_tertiary|Shiftedb|Shift_Trimmedb->b.shifted_tertiaryletquaternary_of_keybuf=functionNon_ignorableb->b.non_ignorable_quaternary|Blankedb->b.blanked_quaternary|Shiftedb|Shift_Trimmedb->b.shifted_quaternaryletaddcekeybufce=(* Printf.printf "addce ce: %x " ce; *)matchkeybufwithNon_ignorablekeybuf->addce_non_ignorablekeybufce|Blankedkeybuf->addce_blankedkeybufce|Shiftedkeybuf|Shift_Trimmedkeybuf->addce_shiftedkeybufceletterminate=functionNon_ignorablekeybuf->terminate_non_ignorablekeybuf|Blankedkeybuf->terminate_blankedkeybuf|Shiftedkeybuf->terminate_shiftedkeybuf|Shift_Trimmedkeybuf->terminate_shift_trimmedkeybufletrecadd_listkeybuf=function[]->()|e::rest->addcekeybufe;add_listkeybufrestletimplicit_cecebufu=letn=UChar.uint_codeuinifn<0||n>0x10ffff||(matchUCharInfo.general_categoryuwith`Cs->true|_->false)||is_noncharacter_code_pointuthenaddcecebufUnidata.complete_ignorable(*illegal code point*)elseletbase=ifn>=0x4e00&&n<=0x9fffthen0xfb40elseifn>=0x3400&&n<=0x4dbfthen0xfb80elseifn>=0x20000&&n<=0x2a6dfthen0xfb80else0xfbc0inleta=base+nlsr15inletb=(nland0x7fff)lor0x8000inaddcecebuf(Unidata.compose_cea11);addcecebuf(Unidata.compose_ceb00)letrecmatch_us2xic'=function[]->[]|(u::rest)asus->ifi>=XString.lengthxthenraiseExitelseletu'=XString.getxiinletc=UCharInfo.combined_classu'inifc'=0||c=0||c'=cthenraiseExitelseifUChar.equu'theni::(match_us2x(i+1)c'rest)elsematch_us2x(i+1)cusletrecmatch_us1xi=function[]->i|(u::rest)asus->ifi>=XString.lengthxthenraiseExitelseletu'=XString.getxiinifUChar.equu'thenmatch_us1x(i+1)restelseletps=match_us2x(i+1)(UCharInfo.combined_classu')usinremove_charsxipsletreclongest_matchce_bufxi=function[]->assertfalse|(us,ces)::rest->tryletj=match_us1xiusinadd_listce_bufces;jwithExit->longest_matchce_bufxirestletgetcekeybufxi=letcol_info=col_info_of_keybufkeybufinlethiraganaQ_mark=Unidata.compose_cecol_info.hiraganaQ_weight00inletrecloopi=ifi>=XString.lengthxthen()elseletu=XString.getxiin(matchUCharInfo.scriptuwith`Hiraganawhencol_info.hiraganaQ->addcekeybufhiraganaQ_mark|_->());leti'=matchUnidata.cecol_info.tbluwith[]->implicit_cekeybufu;i+1|[([],[ce])]->addcekeybufce;i+1|info->longest_matchkeybufx(i+1)infoinloopi'inloopiletgetkeykeybuf=letcol_info=col_info_of_keybufkeybufinletprec=precision_of_keybufkeybufinterminatekeybuf;letbuf1=primary_of_keybufkeybufin(matchprecwith`Primary->()|_->add_i16buf10;letbuf2=secondary_of_keybufkeybufinifcol_info.french_accentthenletkey2=Buffer.to_bytesbuf2inreversekey2;Buffer.add_bytesbuf1key2elseBuffer.add_bufferbuf1buf2;matchprecwith`Secondary->()|_->add_i16buf10;Buffer.add_bufferbuf1(tertiary_of_keybufkeybuf);matchprecwith`Tertiary->()|_->add_i16buf10;Buffer.add_bufferbuf1(quaternary_of_keybufkeybuf));Buffer.contentsbuf1typetext=Text.ttypeindex=Text.indexmoduleNF=UNF.Make(Config)(Text)letsort_key_auxcol_infoprect=letx=XString.make0(UChar.chr_of_uint0)inNF.put_nfdxt;rearrangex;remove_ignorablecol_info.Unidata.tblx;letcebuf=create_keybufpreccol_infoingetcecebufx0;getkeycebufletsort_key?locale?prec?variabletext=letcol_info=letdefault=Unidata.get_col_info?locale()inmatchvariablewithNone->default|Somev->{defaultwithvariable_option=v}inletprec=matchprecwithNone->(matchcol_info.variable_optionwith`Shifted|`Shift_Trimmed->`Quaternary|_->`Tertiary)|Someprec->precinsort_key_auxcol_infoprectext(* Incremental sorting and search *)letrecprimaries_of_cescol_info=function[]->[]|ce::rest->(* Printf.printf "ce: %x " ce; *)letw=letw=Unidata.primaryceinifw=col_info.Unidata.hiraganaQ_weightthen0elsematchcol_info.variable_optionwith`Non_ignorable->w|_->ifis_variablecol_info.variable_topcethen0elsewinifw=0thenprimaries_of_cescol_inforestelsew::primaries_of_cescol_inforestletrecinc_endi=`Inc([],i,lazy(inc_endi))letinc_primcol_info(`Inc(ces,i,f))=letrecloopifws=let`Inc(ces,i',f)=Lazy.forcefinifces=[]then`Inc(ws,i,lazy(inc_endi))elsematchprimaries_of_cescol_infoceswith[]->loopi'fws|ws'->`Inc(ws,i,lazy(loopi'fws'))inloopif(primaries_of_cescol_infoces)letimplicit_ce_listu=letn=UChar.uint_codeuinifn<0||n>0x10ffff||matchUCharInfo.general_categoryuwith`Cs->true|_->false||is_noncharacter_code_pointuthen[Unidata.complete_ignorable](*illegal code point*)elseletbase=ifn>=0x4e00&&n<=0x9fffthen0xfb40elseifn>=0x3400&&n<=0x4dbfthen0xfb80elseifn>=0x20000&&n<=0x2a6dfthen0xfb80else0xfbc0inleta=base+nlsr15inletb=(nland0x7fff)lor0x8000in[Unidata.compose_cea11;Unidata.compose_ceb00]letrecinc_match_us2ifus0us1c'=function[]->`Match(us0@us1,i,f)|(u::rest)asus->matchus1with[]->let`Inc(us1,i,f)=Lazy.forcefinifus1=[]then`Not_Matchelseinc_match_us2ifus0us1c'us|u'::r'->letc=UCharInfo.combined_classu'inifc'=0||c=0||c'=cthen`Not_MatchelseifUChar.equu'theninc_match_us2ifus0r'c'restelseinc_match_us2if(us0@[u'])r'cusletrecinc_match_us1ifus1=function[]->`Match(us1,i,f)|(u::rest)asus->matchus1with[]->let`Inc(us1,i,f)=Lazy.forcefinifus1=[]then`Not_Matchelseinc_match_us1ifus1us|u'::r'->ifUChar.equu'theninc_match_us1ifr'restelseinc_match_us2if[u']r'(UCharInfo.combined_classu')usletrecinc_longest_matchusif=function[]->`Not_Match|(us1,ces)::rest->matchinc_match_us1ifusus1with`Match(us,i,f)->`Match(ces,us,i,f)|`Not_Match->inc_longest_matchusifrestletget_next_cecol_infoifuus=matchUnidata.cecol_info.Unidata.tbluwith[]->(implicit_ce_listu,us,i,f)|[([],ces)]->(ces,us,i,f)|info->matchinc_longest_matchusifinfowith`Not_Match->(implicit_ce_listu,us,i,f)|`Match(ces,us,i,f)->(ces,us,i,f)letget_cescol_infofti=lethiraganaQ_mark=Unidata.compose_cecol_info.Unidata.hiraganaQ_weight00inletrecloopifa=function[]->(matchLazy.forcefwith`Inc([],i,_)->`Inc(a,i,lazy(inc_endi))|`Inc(us,i',f)->matchawith[]->loopi'faus|_->`Inc(a,i,lazy(loopi'f[]us)))|u::us->leta=matchUCharInfo.scriptuwith`Hiraganawhencol_info.hiraganaQ->a@[hiraganaQ_mark]|_->ainletces,us,i,f=get_next_cecol_infoifuusinloopif(a@ces)usinlet`Inc(us,i,f)=ftiinloopif[]usletinc_prepcol_infofti=letrecloopifpreva=function[]->(matcha,prevwith[],_|_,[_]->(matchLazy.forcefwith`Inc([],i,_)->`Inc(a@prev,i,lazy(inc_endi))|`Inc(us,i,f)->loopifprevaus)|_->`Inc(a,i,lazy(loopif[][][])))|u::rest->(* Printf.printf "prep uchar %x " (UChar.code u); *)matchUnidata.cecol_info.Unidata.tbluwith[([],[ce])]whence=Unidata.complete_ignorable->(* Printf.printf "discarded "; *)loopifprevarest|_->matchprevwith[]->ifis_logical_order_exceptionuthenloopif[u]arestelseloopif[](a@[u])rest|[u0]->loopif[](a@[u;u0])rest|_->assertfalseinlet`Inc(us,i,f)=ftiinloopif[][]usletinc_cecol_infoti=get_cescol_info(inc_prepcol_infoNF.nfd_inc)tiletkey_of_incpreccol_infox=letkeybuf=create_keybufpreccol_infoinletrecloop(`Inc(ces,_,f))=add_listkeybufces;matchceswith[]->()|_->loop(Lazy.forcef)inloopx;getkeykeybufletnull_weightf=matchLazy.forcefwith`Inc([],_,_)->true|_->falseletinc_comparepreccol_infot1t2=letrecloopf1f2ws1ws2=matchws1,ws2withw1::rest1,w2::rest2->letsgn=w1-w2inifsgn=0thenloopf1f2rest1rest2elsesgn|[],ws2->let`Inc(ws1,_,f1)=Lazy.forcef1inifws1=[]thenifws2=[]&&null_weightf2then0else~-1elseloopf1f2ws1ws2|ws1,[]->let`Inc(ws2,_,f2)=Lazy.forcef2inifws2=[]then1elseloopf1f2ws1ws2inletx1=inc_cecol_infot1(Text.ntht10)inletx2=inc_cecol_infot2(Text.ntht10)inlet`Inc(ws1,_,g1)=inc_primcol_infox1inlet`Inc(ws2,_,g2)=inc_primcol_infox2inletsgn=loopg1g2ws1ws2inifsgn<>0thensgnelsematchprecwith`Primary->0|_->letkey1=key_of_incpreccol_infox1inletkey2=key_of_incpreccol_infox2inPervasives.comparekey1key2letcompare?locale?prec?variablet1t2=letcol_info=letdefault=Unidata.get_col_info?locale()inmatchvariablewithNone->default|Somev->{defaultwithvariable_option=v}inletprec=matchprecwithNone->(matchcol_info.variable_optionwith`Shifted|`Shift_Trimmed->`Quaternary|_->`Tertiary)|Someprec->precininc_comparepreccol_infot1t2letget_weightki=(Char.codek.[i])lsl8lor(Char.codek.[i+1])letrecprimary_lengthki=ifString.lengthk<=i||get_weightki=0thenielseprimary_lengthk(i+2)letinc_compare_keypreccol_infokt=letk_len=primary_lengthk0inletrecloopfwsi=matchwswithw::rest->(* Printf.printf "prim %x " w; *)ifk_len<=ithen~-1elseletw'=get_weightkiinletsgn=w'-winifsgn=0thenloopfrest(i+2)elsesgn|[]->let`Inc(ws,_,f)=Lazy.forcefinifws=[]thenifk_len=ithen0elseifk_len>ithen1elseassertfalseelseloopfwsiinletx=inc_cecol_infot(Text.ntht0)inlet`Inc(ws,_,g)=inc_primcol_infoxinletsgn=loopgws0in(* print_newline ();*)ifsgn<>0thensgnelsematchprecwith`Primary->0|_->letkey=key_of_incpreccol_infoxin(* Printf.printf "key_of_inc %s\n" (String.escaped key);*)Pervasives.comparekkeyletcompare_with_key?locale?prec?variablekt=letcol_info=letdefault=Unidata.get_col_info?locale()inmatchvariablewithNone->default|Somev->{defaultwithvariable_option=v}inletprec=matchprecwithNone->(matchcol_info.variable_optionwith`Shifted|`Shift_Trimmed->`Quaternary|_->`Tertiary)|Someprec->precininc_compare_keypreccol_infoktletsearch_commoncol_infoprecktloc=letk_len=primary_lengthk0inletrecnullif=let`Inc(ces,j,f)=Lazy.forcefinifprimaries_of_cescol_infoces=[]thennulljfelseiinletrectest_matchifj=functionw::rest->(* Printf.printf "prim %x : loc %d " w j; *)ifk_len<=jthenraiseExitelseletw'=get_weightkjinifw'=wthentest_matchif(j+2)restelseraiseExit|[]->ifk_len=jthen(i,nullif)elselet`Inc(ces,i,f)=Lazy.forcefinifces=[]thenraiseExitelsetest_matchifj(primaries_of_cescol_infoces)inletkeyslocfijces=letkeybuf=create_keybufpreccol_infoinadd_listkeybufces;letrecloopfks=let`Inc(ces,loc,f)=Lazy.forcefinifText.compare_indextlocj>0||ces=[]thenkselsebeginadd_listkeybufces;ifText.compare_indextloci>=0thenloopf((getkeykeybuf,i)::ks)elseloopfksendinifText.compare_indextloci>=0thenloopf[(getkeykeybuf,i)]elseloopf[]inletrecscanlocf=let`Inc(ces,i,f)=Lazy.forcefinifces=[]thenraiseNot_foundelsetrylet(i,j)=test_matchif0(primaries_of_cescol_infoces)inmatchprecwith`Primary->(loc,j)|_->letks=keyslocfijcesin(* Printf.printf "%s %s " (String.escaped k) (String.escaped k'); *)try(loc,List.assockks)withNot_found->raiseExitwithExit->scanifinscanloc(lazy(inc_cecol_infotloc))letsearch_with_key?locale?prec?variablektloc=letcol_info=letdefault=Unidata.get_col_info?locale()inmatchvariablewithNone->default|Somev->{defaultwithvariable_option=v}inletprec=matchprecwithNone->(matchcol_info.variable_optionwith`Shifted|`Shift_Trimmed->`Quaternary|_->`Tertiary)|Someprec->precinsearch_commoncol_infoprecktlocletsearch?locale?prec?variablet0tloc=letk=sort_key?locale?prec?variablet0insearch_with_key?locale?prec?variablektlocend