123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276(*
* oBus_name.ml
* ------------
* Copyright : (c) 2008, Jeremie Dimino <jeremie@dimino.org>
* Licence : BSD3
*
* This file is a part of obus, an ocaml implementation of D-Bus.
*)openStringopenOBus_stringtypebus=stringtypeinterface=stringtypemember=stringtypeerror=string(* +-----------------------------------------------------------------+
| Bus names |
+-----------------------------------------------------------------+ *)letis_uniquename=lengthname>0&&unsafe_getname0=':'letvalidate_unique_connectionstr=letfailimsg=Some{typ="unique connection name";str=str;ofs=i;msg=msg}andlen=lengthstrinletrecelement_starti=ifi=lenthenfaili"empty element"elsematchunsafe_getstriwith|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->element(i+1)|'.'->faili"empty element"|_->faili"invalid character"andelementi=ifi=lenthenNoneelsematchunsafe_getstriwith|'.'->element_start(i+1)|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->element(i+1)|_->faili"invalid character"andfirst_elementi=ifi=lenthenfail(-1)"must contains at least two elements"elsematchunsafe_getstriwith|'.'->element_start(i+1)|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->first_element(i+1)|_->faili"invalid character"iniflen>OBus_protocol.max_name_lengththenfail(-1)"name too long"elseiflen=1thenfail1"premature end of name"elsematchunsafe_getstr1with|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->first_element2|'.'->fail1"empty element"|_->fail1"invalid character"letvalidate_bus_otherstr=letfailimsg=Some{typ="unique connection name";str=str;ofs=i;msg=msg}andlen=lengthstrinletrecelement_starti=ifi=lenthenfaili"empty element"elsematchunsafe_getstriwith|'A'..'Z'|'a'..'z'|'_'|'-'->element(i+1)|'.'->faili"empty element"|_->faili"invalid character"andelementi=ifi=lenthenNoneelsematchunsafe_getstriwith|'.'->element_start(i+1)|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->element(i+1)|_->faili"invalid character"andfirst_elementi=ifi=lenthenfail(-1)"must contains at least two elements"elsematchunsafe_getstriwith|'.'->element_start(i+1)|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->first_element(i+1)|_->faili"invalid character"iniflen>OBus_protocol.max_name_lengththenfail(-1)"name too long"elsematchunsafe_getstr1with|'A'..'Z'|'a'..'z'|'_'|'-'|'0'..'9'->first_element2|'.'->element_start2|_->fail1"invalid character"letvalidate_bus=function|""->Some{typ="bus name";str="";ofs=-1;msg="empty name"}|str->matchunsafe_getstr0with|':'->validate_unique_connectionstr|'A'..'Z'|'a'..'z'|'_'|'-'->validate_bus_otherstr|'.'->Some{typ="bus name";str=str;ofs=0;msg="empty element"}|_->Some{typ="bus name";str=str;ofs=0;msg="invalid character"}(* +-----------------------------------------------------------------+
| Interface names |
+-----------------------------------------------------------------+ *)letvalidate_interfacestr=letfailimsg=Some{typ="interface name";str=str;ofs=i;msg=msg}andlen=lengthstrinletrecelement_starti=ifi=lenthenfaili"empty element"elsematchunsafe_getstriwith|'A'..'Z'|'a'..'z'|'_'->element(i+1)|'.'->faili"empty element"|_->faili"invalid character"andelementi=ifi=lenthenNoneelsematchunsafe_getstriwith|'.'->element_start(i+1)|'A'..'Z'|'a'..'z'|'_'|'0'..'9'->element(i+1)|_->faili"invalid character"andfirst_elementi=ifi=lenthenfail(-1)"must contains at least two elements"elsematchunsafe_getstriwith|'.'->element_start(i+1)|'A'..'Z'|'a'..'z'|'_'|'0'..'9'->first_element(i+1)|_->faili"invalid character"iniflen>OBus_protocol.max_name_lengththenfail(-1)"name too long"elseiflen=0thenfail(-1)"empty name"elsematchunsafe_getstr0with|'A'..'Z'|'a'..'z'|'_'->first_element1|'.'->fail0"empty element"|_->fail0"invalid character"(* +-----------------------------------------------------------------+
| Member names |
+-----------------------------------------------------------------+ *)letvalidate_memberstr=letfailimsg=Some{typ="member name";str=str;ofs=i;msg=msg}andlen=lengthstrinletrecauxi=ifi=lenthenNoneelsematchunsafe_getstriwith|'A'..'Z'|'a'..'z'|'_'|'0'..'9'->aux(i+1)|_->faili"invalid character"iniflen>OBus_protocol.max_name_lengththenfail(-1)"name too long"elseiflen=0thenfail(-1)"empty name"elsematchunsafe_getstr0with|'A'..'Z'|'a'..'z'|'_'->aux1|_->fail0"invalid character"(* +-----------------------------------------------------------------+
| Error names |
+-----------------------------------------------------------------+ *)letvalidate_errorstr=(* Error names have the same restriction as interface names *)matchvalidate_interfacestrwith|None->None|Someerror->Some{errorwithtyp="error name"}(* +-----------------------------------------------------------------+
| Name translation |
+-----------------------------------------------------------------+ *)(* Split a name into blocks. Blocks are the longest sub-strings
matched by the regulare expression: "[A-Z]*[^A-Z.]*" *)letsplitname=(* Recognize the first part of a block: "[A-Z]*" *)letrecpart1i=ifi=String.lengthnamethenielsematchname.[i]with|'A'..'Z'->part1(i+1)|_->part2i(* Recognize the second part of a block: "[^A-Z.]*" *)andpart2i=ifi=String.lengthnamethenielsematchname.[i]with|'A'..'Z'|'.'->i|_->part2(i+1)inletrecspliti=ifi=String.lengthnamethen[]elseletj=part1iinifj=ithen(* Skip empty blocks *)split(i+1)elseString.subnamei(j-i)::splitjinsplit0letocaml_lidname=String.uncapitalize_ascii(String.concat"_"(List.mapString.lowercase_ascii(splitname)))letocaml_uidname=String.capitalize_ascii(String.concat"_"(List.mapString.lowercase_ascii(splitname)))lethaskell_lidname=String.uncapitalize_ascii(String.concat""(splitname))lethaskell_uidname=String.capitalize_ascii(String.concat""(splitname))