(* $Id: charmap.ml,v 1.11 2006/08/13 17:09:17 yori Exp $ *) (* Copyright 2002 Yamagata Yoriyuki *) module type Interface = sig type enc_to_ucs val make_enc_to_ucs : int -> (string * int) list -> enc_to_ucs val no_char_of : enc_to_ucs -> int type probe_state val start_probe : enc_to_ucs -> probe_state val look_probe : probe_state -> int -> int val next_probe : probe_state -> int -> probe_state option type t = { name : string; ucs_to_enc : string Tbl31.t; enc_to_ucs : enc_to_ucs; } type data = Alias of string | CMap of t val of_name : string -> t end module Configure (Config : ConfigInt.Type) = struct type enc_to_ucs = {enc_to_ucs_no_char : int; enc_to_ucs_tbl : Byte_labeled_dag.bytes} let make_enc_to_ucs no_char vs = {enc_to_ucs_no_char = no_char; enc_to_ucs_tbl = Byte_labeled_dag.make_bytes no_char vs} let no_char_of enc_to_ucs = enc_to_ucs.enc_to_ucs_no_char type probe_state = Byte_labeled_dag.bytes let start_probe enc_to_ucs = enc_to_ucs.enc_to_ucs_tbl let look_probe state i = Byte_labeled_dag.look_leaf_bytes state i let next_probe state i = Byte_labeled_dag.look_branch_bytes state i type t = {name : string; ucs_to_enc : string Tbl31.t; enc_to_ucs : enc_to_ucs} type data = Alias of string | CMap of t let loaded = Hashtbl.create 0 let of_name name = try let b = Hashtbl.find loaded name in match Weak.get b 0 with None -> Hashtbl.remove loaded name; raise Not_found | Some x -> x with Not_found -> let rec look count name = let filename = Filename.concat Config.charmapdir (name ^ ".mar") in let c = try open_in_bin filename with Sys_error _ -> raise Not_found in let data : data = input_value c in match data with Alias s -> if count = 1 then raise Not_found else look 1 s | CMap t -> t in let t = look 0 name in let b = Weak.create 1 in Weak.set b 0 (Some t); Hashtbl.add loaded name b; t end