|
rpm-build |
0f2925 |
(*
|
|
rpm-build |
0f2925 |
* ExtHashtbl, extra functions over hashtables.
|
|
rpm-build |
0f2925 |
* Copyright (C) 2003 Nicolas Cannasse
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is free software; you can redistribute it and/or
|
|
rpm-build |
0f2925 |
* modify it under the terms of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License as published by the Free Software Foundation; either
|
|
rpm-build |
0f2925 |
* version 2.1 of the License, or (at your option) any later version,
|
|
rpm-build |
0f2925 |
* with the special exception on linking described in file LICENSE.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is distributed in the hope that it will be useful,
|
|
rpm-build |
0f2925 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
0f2925 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
0f2925 |
* Lesser General Public License for more details.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* You should have received a copy of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License along with this library; if not, write to the Free Software
|
|
rpm-build |
0f2925 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
rpm-build |
0f2925 |
*)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module Hashtbl =
|
|
rpm-build |
0f2925 |
struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML >= 400
|
|
rpm-build |
0f2925 |
external old_hash_param :
|
|
rpm-build |
0f2925 |
int -> int -> 'a -> int = "caml_hash_univ_param" "noalloc"
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type ('a, 'b) h_bucketlist =
|
|
rpm-build |
0f2925 |
| Empty
|
|
rpm-build |
0f2925 |
| Cons of 'a * 'b * ('a, 'b) h_bucketlist
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML >= 400
|
|
rpm-build |
0f2925 |
type ('a, 'b) h_t = {
|
|
rpm-build |
0f2925 |
mutable size: int;
|
|
rpm-build |
0f2925 |
mutable data: ('a, 'b) h_bucketlist array;
|
|
rpm-build |
0f2925 |
mutable seed: int;
|
|
rpm-build |
0f2925 |
initial_size: int;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
#else
|
|
rpm-build |
0f2925 |
type ('a, 'b) h_t = {
|
|
rpm-build |
0f2925 |
mutable size: int;
|
|
rpm-build |
0f2925 |
mutable data: ('a, 'b) h_bucketlist array
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
include Hashtbl
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 400
|
|
rpm-build |
0f2925 |
let create ?random:_ n = Hashtbl.create (* no seed *) n
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
external h_conv : ('a, 'b) t -> ('a, 'b) h_t = "%identity"
|
|
rpm-build |
0f2925 |
external h_make : ('a, 'b) h_t -> ('a, 'b) t = "%identity"
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let exists = mem
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let enum h =
|
|
rpm-build |
0f2925 |
let rec make ipos ibuck idata icount =
|
|
rpm-build |
0f2925 |
let pos = ref ipos in
|
|
rpm-build |
0f2925 |
let buck = ref ibuck in
|
|
rpm-build |
0f2925 |
let hdata = ref idata in
|
|
rpm-build |
0f2925 |
let hcount = ref icount in
|
|
rpm-build |
0f2925 |
let force() =
|
|
rpm-build |
0f2925 |
(** this is a hack in order to keep an O(1) enum constructor **)
|
|
rpm-build |
0f2925 |
if !hcount = -1 then begin
|
|
rpm-build |
0f2925 |
hcount := (h_conv h).size;
|
|
rpm-build |
0f2925 |
hdata := Array.copy (h_conv h).data;
|
|
rpm-build |
0f2925 |
end;
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let rec next() =
|
|
rpm-build |
0f2925 |
force();
|
|
rpm-build |
0f2925 |
match !buck with
|
|
rpm-build |
0f2925 |
| Empty ->
|
|
rpm-build |
0f2925 |
if !hcount = 0 then raise Enum.No_more_elements;
|
|
rpm-build |
0f2925 |
incr pos;
|
|
rpm-build |
0f2925 |
buck := Array.unsafe_get !hdata !pos;
|
|
rpm-build |
0f2925 |
next()
|
|
rpm-build |
0f2925 |
| Cons (k,i,next_buck) ->
|
|
rpm-build |
0f2925 |
buck := next_buck;
|
|
rpm-build |
0f2925 |
decr hcount;
|
|
rpm-build |
0f2925 |
(k,i)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let count() =
|
|
rpm-build |
0f2925 |
if !hcount = -1 then (h_conv h).size else !hcount
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let clone() =
|
|
rpm-build |
0f2925 |
force();
|
|
rpm-build |
0f2925 |
make !pos !buck !hdata !hcount
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
Enum.make ~next ~count ~clone
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
make (-1) Empty (Obj.magic()) (-1)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let keys h =
|
|
rpm-build |
0f2925 |
Enum.map (fun (k,_) -> k) (enum h)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let values h =
|
|
rpm-build |
0f2925 |
Enum.map (fun (_,v) -> v) (enum h)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let map f h =
|
|
rpm-build |
0f2925 |
let rec loop = function
|
|
rpm-build |
0f2925 |
| Empty -> Empty
|
|
rpm-build |
0f2925 |
| Cons (k,v,next) -> Cons (k,f v,loop next)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
h_make { (h_conv h) with
|
|
rpm-build |
0f2925 |
data = Array.map loop (h_conv h).data;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML >= 400
|
|
rpm-build |
0f2925 |
(* copied from stdlib :( *)
|
|
rpm-build |
0f2925 |
let key_index h key =
|
|
rpm-build |
0f2925 |
(* compatibility with old hash tables *)
|
|
rpm-build |
0f2925 |
if Obj.size (Obj.repr h) >= 3
|
|
rpm-build |
0f2925 |
then (seeded_hash_param 10 100 (h_conv h).seed key) land (Array.length (h_conv h).data - 1)
|
|
rpm-build |
0f2925 |
else (old_hash_param 10 100 key) mod (Array.length (h_conv h).data)
|
|
rpm-build |
0f2925 |
#else
|
|
rpm-build |
0f2925 |
let key_index h key = (hash key) mod (Array.length (h_conv h).data)
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let remove_all h key =
|
|
rpm-build |
0f2925 |
let hc = h_conv h in
|
|
rpm-build |
0f2925 |
let rec loop = function
|
|
rpm-build |
0f2925 |
| Empty -> Empty
|
|
rpm-build |
0f2925 |
| Cons(k,v,next) ->
|
|
rpm-build |
0f2925 |
if k = key then begin
|
|
rpm-build |
0f2925 |
hc.size <- pred hc.size;
|
|
rpm-build |
0f2925 |
loop next
|
|
rpm-build |
0f2925 |
end else
|
|
rpm-build |
0f2925 |
Cons(k,v,loop next)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let pos = key_index h key in
|
|
rpm-build |
0f2925 |
Array.unsafe_set hc.data pos (loop (Array.unsafe_get hc.data pos))
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find_default h key defval =
|
|
rpm-build |
0f2925 |
let rec loop = function
|
|
rpm-build |
0f2925 |
| Empty -> defval
|
|
rpm-build |
0f2925 |
| Cons (k,v,next) ->
|
|
rpm-build |
0f2925 |
if k = key then v else loop next
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let pos = key_index h key in
|
|
rpm-build |
0f2925 |
loop (Array.unsafe_get (h_conv h).data pos)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
#if OCAML < 405
|
|
rpm-build |
0f2925 |
let find_opt h key =
|
|
rpm-build |
0f2925 |
let rec loop = function
|
|
rpm-build |
0f2925 |
| Empty -> None
|
|
rpm-build |
0f2925 |
| Cons (k,v,next) ->
|
|
rpm-build |
0f2925 |
if k = key then Some v else loop next
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let pos = key_index h key in
|
|
rpm-build |
0f2925 |
loop (Array.unsafe_get (h_conv h).data pos)
|
|
rpm-build |
0f2925 |
#endif
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find_option = find_opt
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let of_enum e =
|
|
rpm-build |
0f2925 |
let h = create (if Enum.fast_count e then Enum.count e else 0) in
|
|
rpm-build |
0f2925 |
Enum.iter (fun (k,v) -> add h k v) e;
|
|
rpm-build |
0f2925 |
h
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let length h =
|
|
rpm-build |
0f2925 |
(h_conv h).size
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
end
|