Safety commit
[SXSI/xpathcomp.git] / tree.ml
diff --git a/tree.ml b/tree.ml
index 0a31e83..1ff2082 100644 (file)
--- a/tree.ml
+++ b/tree.ml
@@ -28,7 +28,7 @@ let equal_node : 'a node -> 'a node -> bool = (==)
   
 external parse_xml_uri : string -> int -> bool -> bool -> tree = "caml_call_shredder_uri"         
 external parse_xml_string :  string -> int -> bool -> bool -> tree = "caml_call_shredder_string"
-  
+external tree_print_xml_fast3 : tree -> [`Tree ] node -> Unix.file_descr ->unit = "caml_xml_tree_print"
 external tree_save : tree -> Unix.file_descr -> unit = "caml_xml_tree_save"
 external tree_load : Unix.file_descr -> tree = "caml_xml_tree_load"
   
@@ -53,6 +53,7 @@ external text_get_cached_text : tree -> [`Text] node -> string = "caml_text_coll
     
 external tree_root : tree -> [`Tree] node = "caml_xml_tree_root" 
 external tree_subtree_size : tree -> [`Tree] node -> int = "caml_xml_tree_subtree_size"
+external tree_subtree_elements : tree -> [`Tree] node -> int = "caml_xml_tree_subtree_elements"
  
 let tree_is_nil x = equal_node x nil
 
@@ -60,6 +61,8 @@ external tree_parent : tree -> [`Tree] node -> [`Tree] node = "caml_xml_tree_par
 external tree_parent_doc : tree -> [`Text ] node -> [`Tree ] node = "caml_xml_tree_parent_doc" "noalloc"
 (*external tree_prev_doc : tree -> [`Text ] node -> [`Tree ] node = "caml_xml_tree_prev_doc" "noalloc" *)
 external tree_first_child : tree -> [`Tree] node -> [`Tree] node = "caml_xml_tree_first_child" "noalloc"
+external tree_closing : tree -> [`Tree] node -> [`Tree] node = "caml_xml_tree_closing" "noalloc"
+external tree_is_open : tree -> [`Tree] node -> bool = "caml_xml_tree_is_open" "noalloc"
 external tree_first_element : tree -> [`Tree] node -> [`Tree] node = "caml_xml_tree_first_element" "noalloc"
 external tree_tagged_child : tree -> [`Tree] node -> Tag.t -> [`Tree] node = "caml_xml_tree_tagged_child" "noalloc" 
 external tree_next_sibling : tree -> [`Tree] node -> [`Tree] node = "caml_xml_tree_next_sibling"  "noalloc"
@@ -80,6 +83,7 @@ let tree_is_last t n = equal_node nil (tree_next_sibling t n)
 (*external tree_prev_text : tree -> [`Tree] node -> [`Text ] node = "caml_xml_tree_prev_text" "noalloc" *)
 
 external tree_my_text : tree -> [`Tree] node -> [`Text ] node = "caml_xml_tree_my_text" "noalloc"
+external tree_my_text_unsafe : tree -> [`Tree] node -> [`Text ] node = "caml_xml_tree_my_text_unsafe" "noalloc"
 (*external tree_next_text : tree -> [`Tree] node -> [`Text ] node = "caml_xml_tree_next_text" "noalloc" *)
 external tree_doc_ids : tree -> [`Tree ] node -> [`Text ] node * [`Text ] node = "caml_xml_tree_doc_ids" 
 
@@ -129,6 +133,7 @@ type t = {
   ttable : (Tag.t,(Ptset.Int.t*Ptset.Int.t*Ptset.Int.t*Ptset.Int.t)) Hashtbl.t;
 }
 let subtree_size t i = tree_subtree_size t.doc i
+let subtree_elements t i = tree_subtree_elements t.doc i
 let text_size t = text_size t.doc
 
 module MemUnion = Hashtbl.Make (struct 
@@ -421,9 +426,18 @@ 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
 
@@ -474,6 +488,10 @@ let select_foll_ctx t = fun ts ->
   let v = (ptset_to_vector ts) in ();
     fun n ctx -> tree_select_foll_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
@@ -489,8 +507,92 @@ let array_find a i j =
 
 
   let count t s = text_count t.doc s
-
-  let print_xml_fast outc tree t =
+  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 ) 
+    
+  let print_xml_fast2  =
+    let _ = init_stack () in
+    let h = Hashtbl.create MED_H_SIZE in    
+    let tag_str t = try Hashtbl.find h t with
+       Not_found -> let s = Tag.to_string t in
+       Hashtbl.add h t s;s
+    in
+    let h_att = Hashtbl.create MED_H_SIZE in    
+    let att_str t = try Hashtbl.find h_att t with
+       Not_found -> let s = Tag.to_string t in
+      let attname = String.sub s 3 ((String.length s) -3) in
+      Hashtbl.add h_att t attname;attname
+    in fun outc tree t ->
+      let tree = tree.doc in
+      let fin = tree_closing tree t in
+      let rec loop_tag t tag =
+       if t <= fin then
+       if tree_is_open tree t then
+       (* opening tag *)
+       if tag == Tag.pcdata then 
+       begin
+         output_string outc (text_get_cached_text tree (tree_my_text_unsafe tree t));
+         loop (next2 t) (* skip closing $ *)
+       end
+       else
+       let tagstr = tag_str tag in
+       let _ = output_char outc '<';    
+       output_string outc tagstr in
+       let t' = next t in
+       if tree_is_open tree t' then
+       let _ = push tagstr in
+       let tag' = tree_tag_id tree t' in
+       if tag' == Tag.attribute then let t'' = loop_attr (next t') 0 in 
+       output_string outc ">"; loop t'' else (output_string outc ">";loop_tag t' tag')
+       else (* closing with no content *)
+       let _ = output_string outc "/>" in
+       loop (next t')
+       else
+       begin
+       (* closing tag *)
+         output_string outc "</";
+         output_string outc (pop());
+         output_char outc '>';
+         loop (next t);
+       end
+      and loop t = loop_tag t (tree_tag_id tree t)
+      and loop_attr t n = 
+       if tree_is_open tree t then 
+       let attname = att_str (tree_tag_id tree t) in
+       output_char outc ' ';
+       output_string outc attname;
+       output_string outc "=\"";
+       let t = next t in (* open $@ *)
+       output_string outc (text_get_cached_text tree (tree_my_text_unsafe tree t));
+       output_char outc '"';
+       loop_attr (next3 t) (n+1)
+       else
+       next t (* close @ *)
+      in loop t
+
+  let print_xml_fast  =
+    let h = Hashtbl.create MED_H_SIZE in    
+    let tag_str t = try Hashtbl.find h t with
+       Not_found -> let s = Tag.to_string t in
+       Hashtbl.add h t s;s
+    in
+    let h_att = Hashtbl.create MED_H_SIZE in    
+    let att_str t = try Hashtbl.find h_att t with
+       Not_found -> let s = Tag.to_string t in
+      let attname = String.sub s 3 ((String.length s) -3) in
+      Hashtbl.add h_att t attname;attname
+    in fun outc tree t ->
     let rec loop ?(print_right=true) t = 
       if t != nil 
       then 
@@ -498,18 +600,18 @@ let array_find a i j =
          if tagid==Tag.pcdata
          then 
            begin
-             let tid =  tree_my_text tree.doc t in
+             let tid =  tree_my_text_unsafe tree.doc t in
              output_string outc (text_get_cached_text tree.doc tid);
              if print_right
              then loop (next_sibling tree t);
            end
          else
-           let tagstr = Tag.to_string tagid in
+           let tagstr = tag_str tagid in
            let l = first_child tree t 
            and r = next_sibling tree t 
            in
              output_char outc  '<';
-             output_string outc  tagstr;
+             output_string outc tagstr;
              if l == nil then output_string outc  "/>"
              else 
                if (tag tree l) == Tag.attribute then
@@ -537,10 +639,9 @@ let array_find a i j =
     and loop_attributes a = 
       if a != nil
       then
-      let s = (Tag.to_string (tag tree a)) in
-      let attname = String.sub s 3 ((String.length s) -3) in
+      let attname = att_str (tag tree a) in
       let fsa = first_child tree a in
-      let tid =  tree_my_text tree.doc fsa in
+      let tid =  tree_my_text_unsafe tree.doc fsa in
        output_char outc ' ';
        output_string outc attname;
        output_string outc "=\"";
@@ -612,3 +713,4 @@ let dump_tree fmt tree =
 ;;
 
        
+let print_xml_fast3 t = tree_print_xml_fast3 t.doc