Skip to content

Commit

Permalink
consistency among hash set/map, add a copy function/test
Browse files Browse the repository at this point in the history
  • Loading branch information
bobzhang committed Jan 22, 2018
1 parent df41bc8 commit d8e7e00
Show file tree
Hide file tree
Showing 31 changed files with 660 additions and 302 deletions.
40 changes: 21 additions & 19 deletions jscomp/others/bs_HashMap.ml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ let rec replace_in_bucket ~eq key info cell =
(* if [key] already exists, replace it, otherwise add it
Here we add it to the head, it could be tail
*)
let add0 ~hash ~eq h key value =
let setDone0 ~hash ~eq h key value =
let h_buckets = C.buckets h in
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
let l = Array.unsafe_get h_buckets i in
Expand Down Expand Up @@ -204,21 +204,22 @@ let forEach h f = N.iter0 (B.data h) f
let reduce h init f = N.fold0 (B.data h) init f
let logStats h = logStats0 (B.data h)

let add (type a) (type b ) (type id) (h : (a,b,id) t) (key:a) (info:b) =
let setDone (type a) (type b ) (type id) (h : (a,b,id) t) (key:a) (info:b) =
let dict,data = B.(dict h, data h) in
let module M = (val dict) in
add0 ~hash:M.hash ~eq:M.eq data key info
setDone0 ~hash:M.hash ~eq:M.eq data key info

let remove (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
let dict,data = B.(dict h, data h) in
let module M = (val dict) in
remove0 ~hash:M.hash ~eq:M.eq data key
let set h key info = setDone h key info; h

let removeDone (type a) (type id) (h : (a,_,id) t) (key : a) =
let module M = (val B.dict h) in
remove0 ~hash:M.hash ~eq:M.eq (B.data h) key

let remove h key = removeDone h key; h

let get (type a) (type b) (type id) (h : (a,b,id) t) (key : a) =
let dict,data = B.(dict h, data h) in
let module M = (val dict) in
get0 ~hash:M.hash ~eq:M.eq data key
let module M = (val B.dict h) in
get0 ~hash:M.hash ~eq:M.eq (B.data h) key



Expand All @@ -239,7 +240,7 @@ let ofArray0 ~hash ~eq arr =
let v = create0 len in
for i = 0 to len - 1 do
let key,value = (Bs.Array.unsafe_get arr i) in
add0 ~eq ~hash v key value
setDone0 ~eq ~hash v key value
done ;
v

Expand All @@ -248,7 +249,7 @@ let mergeArrayDone0 h arr ~hash ~eq =
let len = Bs.Array.length arr in
for i = 0 to len - 1 do
let key,value = (Bs_Array.unsafe_get arr i) in
add0 h ~eq ~hash key value
setDone0 h ~eq ~hash key value
done

let mergeArray0 h arr ~hash ~eq = mergeArrayDone0 h arr ~hash ~eq; h
Expand All @@ -261,21 +262,22 @@ let ofArray (type a) (type id)

let mergeArrayDone (type a) (type b) (type id)
(h : (a,b,id) t) arr =
let dict,data = B.(dict h, data h) in
let module M = (val dict) in
let data = B.data h in
let module M = (val B.dict h) in
mergeArrayDone0 ~hash:M.hash ~eq:M.eq data arr


let mergeArray (type a) (type b) (type id)
(h : (a,b,id) t) arr =
mergeArrayDone h arr;
h
let copy h = B.bag ~dict:(B.dict h) ~data:(N.copy (B.data h))

let keys0 = N.keys0
let keys h =
keys0 (B.data h)
let values0 = N.values0
let values h = N.values0 (B.data h)
let keysToArray0 = N.keys0
let keysToArray h =
N.keys0 (B.data h)
let valuesToArray0 = N.values0
let valuesToArray h = N.values0 (B.data h)

let getData = B.data
let getDict = B.dict
Expand Down
92 changes: 24 additions & 68 deletions jscomp/others/bs_HashMap.mli
Original file line number Diff line number Diff line change
Expand Up @@ -29,77 +29,32 @@ type ('a,'b,'id) t

(** The type of hash tables from type ['a] to type ['b]. *)

val create : ('a,'id) Bs_Hash.t -> int -> ('a,'b,'id) t
(** [Hashtbl.create n] creates a new, empty hash table, with
initial size [n]. For best results, [n] should be on the
order of the expected number of elements that will be in
the table. The table grows as needed, so [n] is just an
initial guess.
The optional [random] parameter (a boolean) controls whether
the internal organization of the hash table is randomized at each
execution of [Hashtbl.create] or deterministic over all executions.
A hash table that is created with [~random:false] uses a
fixed hash function ({!Hashtbl.hash}) to distribute keys among
buckets. As a consequence, collisions between keys happen
deterministically. In Web-facing applications or other
security-sensitive applications, the deterministic collision
patterns can be exploited by a malicious user to create a
denial-of-service attack: the attacker sends input crafted to
create many collisions in the table, slowing the application down.
A hash table that is created with [~random:true] uses the seeded
hash function {!Hashtbl.seeded_hash} with a seed that is randomly
chosen at hash table creation time. In effect, the hash function
used is randomly selected among [2^{30}] different hash functions.
All these hash functions have different collision patterns,
rendering ineffective the denial-of-service attack described above.
However, because of randomization, enumerating all elements of the
hash table using {!Hashtbl.fold} or {!Hashtbl.iter} is no longer
deterministic: elements are enumerated in different orders at
different runs of the program.
If no [~random] parameter is given, hash tables are created
in non-random mode by default. This default can be changed
either programmatically by calling {!Hashtbl.randomize} or by
setting the [R] flag in the [OCAMLRUNPARAM] environment variable.
@before 4.00.0 the [random] parameter was not present and all
hash tables were created in non-randomized mode. *)


val clear : ('a, 'b, 'id) t -> unit
val create: ('a,'id) Bs_Hash.t -> int -> ('a,'b,'id) t
(*TODO: allow randomization for security *)

val clear: ('a, 'b, 'id) t -> unit
(** Empty a hash table. Use [reset] instead of [clear] to shrink the
size of the bucket table to its initial size. *)



val add : ('a, 'b, 'id) t -> 'a -> 'b -> unit
(** [Hashtbl.add tbl x y] adds a binding of [x] to [y] in table [tbl].
Previous bindings for [x] are not removed, but simply
hidden. That is, after performing {!Hashtbl.remove}[ tbl x],
the previous binding for [x], if any, is restored.
(Same behavior as with association lists.) *)

val setDone: ('a, 'b, 'id) t -> 'a -> 'b -> unit
val set: ('a, 'b, 'id) t -> 'a -> 'b -> ('a, 'b, 'id) t
val copy: ('a, 'b, 'id) t -> ('a, 'b, 'id) t

val get:
('a, 'b, 'id) t -> 'a -> 'b option


val has: ('a, 'b, 'id) t -> 'a -> bool
(** [Hashtbl.mem tbl x] checks if [x] is bound in [tbl]. *)
(** [has tbl x] checks if [x] is bound in [tbl]. *)

val removeDone:
('a, 'b, 'id) t -> 'a ->
unit
val remove:
('a, 'b, 'id) t -> 'a -> unit
(** [Hashtbl.remove tbl x] removes the current binding of [x] in [tbl],
restoring the previous binding if it exists.
It does nothing if [x] is not bound in [tbl]. *)





('a, 'b, 'id) t -> 'a ->
('a, 'b, 'id) t

val forEach: ('a, 'b, 'id) t -> ('a -> 'b -> unit [@bs]) -> unit
(** [Hashtbl.iter f tbl] applies [f] to all bindings in table [tbl].

This comment has been minimized.

Copy link
@cristianoc

cristianoc Jan 22, 2018

Collaborator

In comment: forEach

Expand Down Expand Up @@ -158,7 +113,7 @@ val logStats : _ t -> unit



val toArray : ('a, 'b, 'id) t -> ('a * 'b) array
val toArray: ('a, 'b, 'id) t -> ('a * 'b) array



Expand All @@ -170,9 +125,9 @@ val ofArray:
val mergeArrayDone: ('a, 'b, 'id) t -> ('a * 'b) array -> unit
val mergeArray: ('a, 'b, 'id) t -> ('a * 'b) array -> ('a, 'b, 'id) t

val keys:
val keysToArray:
('a,'b,'id) t -> 'a array
val values:
val valuesToArray:
('a,'b,'id) t -> 'b array

(****************************************************************************)
Expand All @@ -181,18 +136,19 @@ type ('a, 'b, 'id) t0
val getData: ('k,'v,'id) t -> ('k,'v,'id) t0
val getDict: ('k,'v,'id) t -> ('k,'id) Bs_Hash.t
val packDictData: dict:('k, 'id) Bs_Hash.t -> data:('k, 'v, 'id) t0 -> ('k, 'v, 'id) t
val create0 : int -> ('a, 'b, 'id) t0
val clear0 : ('a, 'b, 'id) t0 -> unit
val add0 :
val create0: int -> ('a, 'b, 'id) t0
val clear0: ('a, 'b, 'id) t0 -> unit
val setDone0 :
hash:('a,'id) Bs_Hash.hash ->
eq:('a,'id) Bs_Hash.eq ->
('a,'b,'id) t0 -> 'a ->
'b -> unit
val get0:
hash:('a,'id) Bs_Hash.hash ->
eq:('a,'id) Bs_Hash.eq ->
('a, 'b, 'id) t0 -> 'a
-> 'b option
('a, 'b, 'id) t0 ->
'a ->
'b option

val has0:
hash:('a,'id) Bs_Hash.hash ->
Expand Down Expand Up @@ -226,9 +182,9 @@ val mergeArray0:
eq:('a,'id) Bs_Hash.eq ->
('a, 'b, 'id) t0

val keys0:
val keysToArray0:
('a,'b,'id) t0 -> 'a array
val values0:
val valuesToArray0:
('a,'b,'id) t0 -> 'b array


18 changes: 12 additions & 6 deletions jscomp/others/bs_HashMapInt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ let rec replace_bucket (key : key) info cell =
| Some cell ->
replace_bucket key info cell

let set h (key : key) value =
let setDone h (key : key) value =
let h_buckets = C.buckets h in
let i = hash key land (Array.length h_buckets - 1) in
let l = Array.unsafe_get h_buckets i in
Expand All @@ -96,6 +96,7 @@ let set h (key : key) value =
end
end

let set h key value = setDone h key value ; h
let rec remove_bucket h h_buckets i (key : key) prec buckets =
match C.toOpt buckets with
| None -> ()
Expand All @@ -109,7 +110,7 @@ let rec remove_bucket h h_buckets i (key : key) prec buckets =
end
else remove_bucket h h_buckets i key cell cell_next

let remove h key =
let removeDone h key =
let h_buckets = C.buckets h in
let i = hash key land (Array.length h_buckets - 1) in
let bucket = (Bs_Array.unsafe_get h_buckets i) in
Expand All @@ -124,7 +125,7 @@ let remove h key =
else
remove_bucket h h_buckets i key cell (N.next cell)


let remove h key = removeDone h key; h

let rec findAux (key : key) buckets =
match C.toOpt buckets with
Expand Down Expand Up @@ -187,7 +188,7 @@ let ofArray arr =
let v = create len in
for i = 0 to len - 1 do
let k,value = (Bs.Array.unsafe_get arr i) in
set v k value
setDone v k value
done ;
v

Expand All @@ -196,7 +197,12 @@ let mergeArrayDone h arr =
let len = Bs.Array.length arr in
for i = 0 to len - 1 do
let k,v = (Bs_Array.unsafe_get arr i) in
set h k v
done
setDone h k v
done

let mergeArray h arr = mergeArrayDone h arr; h

let copy = N.copy

let keysToArray = N.keys0
let valuesToArray = N.values0
12 changes: 8 additions & 4 deletions jscomp/others/bs_HashMapInt.mli
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ val create: int -> 'b t

val clear: 'b t -> unit

val set: 'a t -> key -> 'a -> unit

val setDone: 'a t -> key -> 'a -> unit
val set: 'a t -> key -> 'a -> 'a t
val copy: 'a t -> 'a t
val get: 'a t -> key -> 'a option

val has: 'b t -> key -> bool

val remove: 'a t -> key -> unit
val removeDone: 'a t -> key -> unit
val remove: 'a t -> key -> 'a t

val forEach: 'b t -> (key -> 'b -> unit [@bs]) -> unit

Expand All @@ -28,7 +30,9 @@ val filterMap: 'a t -> (key -> 'a -> 'a option [@bs]) -> 'a t
val size: _ t -> int
val logStats: _ t -> unit

val toArray: 'a t -> (key * 'a) array
val toArray: 'a t -> (key * 'a) array
val keysToArray: 'a t -> key array
val valuesToArray: 'a t -> 'a array
val ofArray: (key * 'a) array -> 'a t
val mergeArrayDone: 'a t -> (key * 'a) array -> unit
val mergeArray: 'a t -> (key * 'a) array -> 'a t
Expand Down
18 changes: 12 additions & 6 deletions jscomp/others/bs_HashMapString.ml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ let rec replace_bucket (key : key) info cell =
| Some cell ->
replace_bucket key info cell

let set h (key : key) value =
let setDone h (key : key) value =
let h_buckets = C.buckets h in
let i = hash key land (Array.length h_buckets - 1) in
let l = Array.unsafe_get h_buckets i in
Expand All @@ -96,6 +96,7 @@ let set h (key : key) value =
end
end

let set h key value = setDone h key value ; h
let rec remove_bucket h h_buckets i (key : key) prec buckets =
match C.toOpt buckets with
| None -> ()
Expand All @@ -109,7 +110,7 @@ let rec remove_bucket h h_buckets i (key : key) prec buckets =
end
else remove_bucket h h_buckets i key cell cell_next

let remove h key =
let removeDone h key =
let h_buckets = C.buckets h in
let i = hash key land (Array.length h_buckets - 1) in
let bucket = (Bs_Array.unsafe_get h_buckets i) in
Expand All @@ -124,7 +125,7 @@ let remove h key =
else
remove_bucket h h_buckets i key cell (N.next cell)


let remove h key = removeDone h key; h

let rec findAux (key : key) buckets =
match C.toOpt buckets with
Expand Down Expand Up @@ -187,7 +188,7 @@ let ofArray arr =
let v = create len in
for i = 0 to len - 1 do
let k,value = (Bs.Array.unsafe_get arr i) in
set v k value
setDone v k value
done ;
v

Expand All @@ -196,7 +197,12 @@ let mergeArrayDone h arr =
let len = Bs.Array.length arr in
for i = 0 to len - 1 do
let k,v = (Bs_Array.unsafe_get arr i) in
set h k v
done
setDone h k v
done

let mergeArray h arr = mergeArrayDone h arr; h

let copy = N.copy

let keysToArray = N.keys0
let valuesToArray = N.values0
Loading

0 comments on commit d8e7e00

Please sign in to comment.