1
(***********************************************************************)
5
(* (C) 2007 by Zheng Li (li@pps.jussieu.fr) *)
7
(* This program is free software; you can redistribute it and/or *)
8
(* modify it under the terms of the GNU Lesser General Public *)
9
(* License version 2.1 as published by the Free Software Foundation, *)
10
(* with the special exception on linking described in file LICENSE. *)
12
(* This program is distributed in the hope that it will be useful, *)
13
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
14
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
15
(* GNU Library General Public License for more details. *)
17
(***********************************************************************)
20
(* weak stack, for ordering purpose *)
22
type 'a t = {mutable data:'a Weak.t; mutable length:int; mutable cursor:int}
24
let len = min n (Sys.max_array_length - 1) in
25
{data = Weak.create len; length = len; cursor = 0}
27
for i = s.cursor -1 downto 0 do
28
match Weak.get s.data i with Some x -> f x | _ -> ()
30
let length s = (* resize by the way, since it's invoked by push *)
31
let flag = ref false and pt = ref 0 in
32
for i = 0 to s.cursor -1 do
33
match Weak.get s.data i with
34
| Some x as d -> if !flag then Weak.set s.data !pt d; incr pt
35
| None -> flag := true
37
s.cursor <- !pt; s.cursor
39
let s' = create s.length in
40
Weak.blit s.data 0 s'.data 0 s.cursor; s'.cursor <- s.cursor; s'
42
if s.cursor < s.length then
43
(Weak.set s.data s.cursor (Some x); s.cursor <- s.cursor + 1)
46
if len >= s.length / 3 && len < s.length * 2 / 3 then push x s else
47
let len' = min (len * 3 / 2 + 2) (Sys.max_array_length -1) in
48
if len' = len then failwith "Weaktbl.Stack.push: stack cannnot grow"
50
let data' = Weak.create len' in
51
Weak.blit s.data 0 data' 0 s.cursor;
52
s.data <- data'; s.length <- len'; push x s
54
if s.cursor <= 0 then raise Not_found;
55
s.cursor <- s.cursor -1;
56
match Weak.get s.data s.cursor with Some x -> x | None -> pop s
58
if s.cursor <= 0 then raise Not_found;
59
match Weak.get s.data (s.cursor -1) with
60
| Some x -> x | None -> s.cursor <- s.cursor -1; top s
61
let is_empty s = (* stop as earlier as we can *)
62
try iter (fun _ -> raise Not_found) s; true with Not_found -> false
65
open Obj (* Recover polymorphism from standard monomorphic (Weak)Hashtbl *)
66
module Make (H: Hashtbl.HashedType) : Hashtbl.S with type key = H.t = struct
68
let enbox k = let w = Weak.create 1 in Weak.set w 0 (Some k); w
69
let unbox bk = Weak.get bk 0
71
let bind_new k v = enbox k, repr v
72
type cls = bind Stack.t
73
let cls_new bd = let cls = Stack.create 1 in Stack.push bd cls; cls
74
let dummy k = cls_new (bind_new k ())
75
let rec top_bind cls =
76
let (bk,v) as bind = Stack.top cls in
78
| Some k -> k, (obj v) | _ -> assert (bind == Stack.pop cls); top_bind cls
79
let top_key cls = fst (top_bind cls) and top_value cls = snd (top_bind cls)
82
let f (bk,v) = match unbox bk with
83
| Some k -> l := (k, obj v) :: !l | _ -> () in
84
Stack.iter f cls; List.rev !l
85
let all_key cls = List.map fst (all_bind cls)
86
and all_value cls = List.map snd (all_bind cls)
89
let hash x = try H.hash (top_key x) with Not_found -> 0
90
let equal x y = try H.equal (top_key x) (top_key y) with Not_found -> false
92
module W = Weak.Make(HX)
93
type key = H.t and 'a t = W.t
94
let create = W.create and clear = W.clear
95
let find_all tbl key =
96
try all_value (W.find tbl (dummy key)) with Not_found-> []
97
let rec find tbl key = top_value (W.find tbl (dummy key))
98
let add tbl key data =
99
let bd = bind_new key data in
101
try let c = W.find tbl (dummy key) in Stack.push bd c; c
102
with Not_found -> let c = cls_new bd in W.add tbl c; c in
103
let final _ = ignore bd; ignore cls in
104
try Gc.finalise final key
105
with Invalid_argument _ -> Gc.finalise final bd; Gc.finalise final cls
107
try ignore (Stack.pop (W.find tbl (dummy key))) with Not_found -> ()
108
let replace tbl key data = remove tbl key; add tbl key data
109
let mem tbl key = try ignore (find tbl key); true with Not_found -> false
111
let f' (bk,v) = match unbox bk with Some k -> f k (obj v) | None -> () in
112
W.iter (Stack.iter f') tbl
113
let fold f tbl accu =
115
let f' k v = r := f k v !r in
117
let length tbl = W.fold (fun cls -> (+) (Stack.length cls)) tbl 0
119
let tbl'= W.create (W.count tbl * 3 / 2 + 2) in
120
W.iter (fun cls -> W.add tbl' (Stack.copy cls)) tbl; tbl'
123
module StdHash = Make
125
type t = Obj.t let equal x y = (compare x y) = 0 let hash = Hashtbl.hash
128
type ('a,'b) t = 'b StdHash.t
129
let create = create and clear = clear and copy = copy and length = length
130
let add tbl k = add tbl (repr k)
131
let remove tbl k = remove tbl (repr k)
132
let find tbl k = find tbl (repr k)
133
let find_all tbl k = find_all tbl (repr k)
134
let replace tbl k = replace tbl (repr k)
135
let mem tbl k = mem tbl (repr k)
136
let iter f = iter (fun k d -> f (obj k) d)
137
let fold f = fold (fun k d a -> f (obj k) d a)