+let parse_xml_uri str = parse parse_xml_uri str
+let parse_xml_string str = parse parse_xml_string str
+
+let size t = tree_size t.doc;;
+
+external pool : tree -> Tag.pool = "%identity"
+
+let magic_string = "SXSI_INDEX"
+let version_string = "2"
+
+let pos fd =
+ Unix.lseek fd 0 Unix.SEEK_CUR
+
+let pr_pos fd = Printf.eprintf "At position %i\n%!" (pos fd)
+
+let write fd s =
+ let sl = String.length s in
+ let ssl = Printf.sprintf "%020i" sl in
+ ignore (Unix.write fd ssl 0 20);
+ ignore (Unix.write fd s 0 (String.length s))
+
+let rec really_read fd buffer start length =
+ if length <= 0 then () else
+ match Unix.read fd buffer start length with
+ 0 -> raise End_of_file
+ | r -> really_read fd buffer (start + r) (length - r);;
+
+let read fd =
+ let buffer = String.create 20 in
+ let _ = really_read fd buffer 0 20 in
+ let size = int_of_string buffer in
+ let buffer = String.create size in
+ let _ = really_read fd buffer 0 size in
+ buffer
+
+
+let save t str =
+ let fd = Unix.openfile str [ Unix.O_WRONLY;Unix.O_TRUNC;Unix.O_CREAT] 0o644 in
+ let out_c = Unix.out_channel_of_descr fd in
+ let _ = set_binary_mode_out out_c true in
+ output_string out_c magic_string;
+ output_char out_c '\n';
+ output_string out_c version_string;
+ output_char out_c '\n';
+ Marshal.to_channel out_c t.ttable [ ];
+ (* we need to move the fd to the correct position *)
+ flush out_c;
+ ignore (Unix.lseek fd (pos_out out_c) Unix.SEEK_SET);
+ tree_save t.doc fd str;
+ close_out out_c
+;;
+
+let load ?(sample=64) ?(load_text=true) str =
+ let fd = Unix.openfile str [ Unix.O_RDONLY ] 0o644 in
+ let in_c = Unix.in_channel_of_descr fd in
+ let _ = set_binary_mode_in in_c true in
+ let load_table () =
+ (let ms = input_line in_c in if ms <> magic_string then failwith "Invalid index file");
+ (let vs = input_line in_c in if vs <> version_string then failwith "Invalid version file");
+ let table : (Tag.t,(Ptset.Int.t*Ptset.Int.t*Ptset.Int.t*Ptset.Int.t)) Hashtbl.t =
+ Marshal.from_channel in_c
+ in
+ let ntable = Hashtbl.create (Hashtbl.length table) in
+ Hashtbl.iter (fun k (s1,s2,s3,s4) ->
+ let ss1 = Ptset.Int.fold (Ptset.Int.add) s1 Ptset.Int.empty
+ and ss2 = Ptset.Int.fold (Ptset.Int.add) s2 Ptset.Int.empty
+ and ss3 = Ptset.Int.fold (Ptset.Int.add) s3 Ptset.Int.empty
+ and ss4 = Ptset.Int.fold (Ptset.Int.add) s4 Ptset.Int.empty
+ in Hashtbl.add ntable k (ss1,ss2,ss3,ss4)
+ ) table;
+ Hashtbl.clear table;
+ (* The in_channel read a chunk of fd, so we might be after
+ the start of the XMLTree save file. Reset to the correct
+ position *)
+ ntable
+ in
+ let _ = Printf.eprintf "\nLoading tag table : " in
+ let ntable = time (load_table) () in
+ ignore(Unix.lseek fd (pos_in in_c) Unix.SEEK_SET);
+ let tree = { doc = tree_load fd str load_text sample;
+ ttable = ntable;}
+ in close_in in_c;
+ tree
+
+
+
+
+let tag_pool t = pool t.doc
+
+let compare = compare_node
+
+let equal a b = a == b
+
+let nts = function
+ -1 -> "Nil"
+ | i -> Printf.sprintf "Node (%i)" i
+
+let dump_node t = nts (inode t)
+
+let is_left t n = tree_is_first_child t.doc n
+
+
+
+let is_below_right t n1 n2 =
+ tree_is_ancestor t.doc (tree_parent t.doc n1) n2
+ && not (tree_is_ancestor t.doc n1 n2)
+
+let is_binary_ancestor t n1 n2 =
+ let p = tree_parent t.doc n1 in
+ let fin = tree_closing t.doc p in
+ n2 > n1 && n2 < fin
+(* (is_below_right t n1 n2) ||
+ (tree_is_ancestor t.doc n1 n2) *)
+
+let parent t n = tree_parent t.doc n
+
+let first_child t = let doc = t.doc in ();fun n -> tree_first_child doc n
+let first_element t = let doc = t.doc in (); fun n -> tree_first_element doc n
+
+(* these function will be called in two times: first partial application
+ on the tag, then application of the tag and the tree, then application of
+ the other arguments. We use the trick to let the compiler optimize application
+*)
+
+let tagged_child t tag = () ; fun n -> tree_tagged_child t.doc n tag
+
+let select_child t = fun ts ->
+ let v = ptset_to_vector ts in ();
+ fun n -> tree_select_child t.doc n v
+
+let next_sibling t = let doc = t.doc in (); fun n -> tree_next_sibling doc n
+let next_element t = let doc = t.doc in (); fun n -> tree_next_element doc n
+
+let tagged_following_sibling t tag = (); fun n -> tree_tagged_following_sibling t.doc n tag
+
+let select_following_sibling t = fun ts ->
+ let v = (ptset_to_vector ts) in ();
+ fun n -> tree_select_following_sibling t.doc n v
+
+let next_sibling_below t = (); fun n _ -> tree_next_sibling t.doc n
+let next_element_below t = (); fun n _ -> tree_next_element t.doc n
+
+let tagged_following_sibling_below t tag = (); fun n _ -> tree_tagged_following_sibling t.doc n tag
+
+let select_following_sibling_below t = fun ts ->
+ let v = (ptset_to_vector ts) in ();
+ fun n _ -> tree_select_following_sibling t.doc n v
+
+let id t n = tree_node_xml_id t.doc n
+
+let tag t n = if n == nil then Tag.nullt else tree_tag t.doc n
+
+let tagged_descendant t tag =
+ let doc = t.doc in (); fun n -> tree_tagged_descendant doc n tag
+
+let select_descendant t = fun ts ->
+ let v = (ptset_to_vector ts) in ();
+ fun n -> tree_select_descendant t.doc n v
+
+let tagged_following_below t tag =
+ let doc = t.doc in
+ (); fun n ctx -> tree_tagged_following_below doc n tag ctx
+
+let select_following_below t = fun ts ->
+ let v = (ptset_to_vector ts) in ();
+ fun n ctx -> tree_select_following_below t.doc n v ctx
+
+let closing t n = tree_closing t.doc n
+let is_open t n = tree_is_open t.doc n
+let get_text_id t n = tree_my_text t.doc n
+
+let last_idx = ref 0
+let array_find a i j =
+ let l = Array.length a in
+ let rec loop idx x y =
+ if x > y || idx >= l then nil
+ else
+ if a.(idx) >= x then if a.(idx) > y then nil else (last_idx := idx;a.(idx))
+ else loop (idx+1) x y
+ in
+ if a.(0) > j || a.(l-1) < i then nil
+ else loop !last_idx i j
+
+
+
+ let count t s = text_count t.doc s
+ let stack = ref []
+ let init_stack () = stack := []
+ let push x = stack:= x::!stack
+ let peek () = match !stack with
+ p::_ -> p
+ | _ -> failwith "peek"
+ let pop () = match !stack with
+ p::r -> stack:=r; p
+ | _ -> failwith "pop"
+
+ let next t = nodei ( (inode t) + 1 )
+ let next2 t = nodei ( (inode t) + 2 )
+ let next3 t = nodei ( (inode t) + 3 )