Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file string_dict.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158openBaseopenPpx_compare_lib.Builtin(* In order to be efficient, we make assumption about the runtime representation of
strings. Essentially we assume that it's OK to see a string as a flat array of words
and that padding bytes are never random.
Since this is probably not portable in Javascript, the primitive that make these
assumptions are written in C, where the value representation is documented. Moreover,
the OCaml compiler is not yet able to generate code that is as efficient as C for the
[find] function.
4.04 introduces [Sys.backend_type], so if we can get the OCaml implementation as
efficient, we can switch back to an OCaml implementation.
*)(* A block. This module only assume that we can split a string into a list of blocks. *)typeblock=nativeint[@@derivingcompare](* (compact) array of blocks *)typeblocks(* These functions are used to compile a association list into a trie *)externalblocks_of_string:string->blocks="Base_string_dict_blocks_of_string"externalget_block:blocks->int->block="Base_string_dict_get_block"externalnum_blocks:blocks->int="Base_string_dict_num_blocks"externalmake_blocks:blockarray->blocks="Base_string_dict_make_blocks"(* A dictionary is organized as a trie. This type is accessed by the C implementation of
[find]. *)type'atrie={num_children:int;(* Block array of length [num_children] *)keys:blocks;(* Array of length [num_children]. [children.(i)] correspond to all the children whose
nth block is [keys.(i)]. *)children:'atriearray;(* If this node correspond to an entry, this is the associated value. *)value:'aoption}type'at={trie:'atrie;(* Sorted association list, used for sexp conversion, comparison and hashing *)alist:(string*'a)list}letto_alistt=t.alist(* This is the only function for which we really care about performance *)externalfind:'atrie->string->'aoption="Base_string_dict_find"[@@noalloc]letfindtkey=findt.triekeyletfind_exntkey=matchfindtkeywith|None->raiseCaml.Not_found|Somex->xmoduleBmap=Caml.Map.Make(structtypet=block[@@derivingcompare]end)letreccheck_no_duplicates_in_sorted_list=function|(a,_)::((b,_)::_asrest)->ifString.compareab=0thenErroraelsecheck_no_duplicates_in_sorted_listrest|_->Ok()letsort_and_check_no_duplicatesl=letl=List.sortl~compare:(fun(a,_)(b,_)->String.compareab)inmatchcheck_no_duplicates_in_sorted_listlwith|Ok()->Okl|Error_aserr->errletof_alistl=matchsort_and_check_no_duplicateslwith|Error_aserr->err|Okalist->letrecloopl~pos=letvalue,l=matchList.partition_tfl~f:(fun(blocks,_)->num_blocksblocks=pos)with|[],l->None,l|[(_,x)],l->Somex,l|_->(* The only way to get here is if we have two entries with the same key, which
we already checked *)assertfalseinletkeys,subs=List.foldl~init:Bmap.empty~f:(funacc((blocks,_)asentry)->letblock=get_blockblocksposinletothers=matchBmap.findblockaccwith|exception(Not_found_s_|Caml.Not_found)->[]|l->linBmap.addblock(entry::others)acc)|>Bmap.bindings|>List.unzipinletkeys=make_blocks(Array.of_listkeys)inletchildren=Array.of_list(List.mapsubs~f:(loop~pos:(pos+1)))in{num_children=Array.lengthchildren;keys;children;value}inlettrie=loop(List.mapalist~f:(fun(s,x)->(blocks_of_strings,x)))~pos:0inOk{trie;alist}letof_alist_exnl=matchof_alistlwith|Okt->t|Errordup->Printf.ksprintfinvalid_arg"Dict.make_exn: duplicate key: %S"dupmoduleFor_conv=structopenHash.Builtintype'at=(string*'a)list[@@derivingcompare,hash]letsexp_of_tfl=Sexp.List(List.mapl~f:(fun(k,v)->Sexp.List[Atomk;fv]))letof_sexp_errormsgsexp=raise(Sexp.Of_sexp_error(Failuremsg,sexp))letstring_of_sexp:Sexp.t->string=function|Atoms->s|sexp->of_sexp_error"atom expected"sexplett_of_sexpf(sexp:Sexp.t)=matchsexpwith|Atom_->of_sexp_error"list expected"sexp|Listl->List.mapl~f:(function|List[k;v]->(string_of_sexpk,fv)|sexp->of_sexp_error"s-expression of the form (_ _) expected"sexp)endletcomparefab=For_conv.comparefa.alistb.alistlethash_fold_tfst=For_conv.hash_fold_tfst.alistletsexp_of_tft=For_conv.sexp_of_tft.alistlett_of_sexpfsexp=letl=For_conv.t_of_sexpfsexpinmatchof_alistlwith|Okt->t|Errordup->letmsg=Printf.sprintf"Dict.t_of_sexp: duplicated key: %S"dupinFor_conv.of_sexp_errormsgsexp