summaryrefslogtreecommitdiff
path: root/stdlib/hashtbl.ml
diff options
context:
space:
mode:
authoralainfrisch <alain@frisch.fr>2016-03-10 14:55:11 +0100
committeralainfrisch <alain@frisch.fr>2016-03-11 11:45:59 +0100
commitbff08d276370904e6d5536ef934c090fa659d55f (patch)
tree3af5bf86ccf31ae535645c7f8d678252fdaa296e /stdlib/hashtbl.ml
parent23b2edf2860f2e9cdfc559553ab32639c7f53064 (diff)
downloadocaml-bff08d276370904e6d5536ef934c090fa659d55f.tar.gz
Adapt filter_map_inplace.
Diffstat (limited to 'stdlib/hashtbl.ml')
-rw-r--r--stdlib/hashtbl.ml40
1 files changed, 29 insertions, 11 deletions
diff --git a/stdlib/hashtbl.ml b/stdlib/hashtbl.ml
index 1004e9950b..8071685535 100644
--- a/stdlib/hashtbl.ml
+++ b/stdlib/hashtbl.ml
@@ -254,19 +254,37 @@ let iter f h =
flip_ongoing_traversal h;
raise exn
+let rec filter_map_inplace_bucket f h i prec = function
+ | Empty ->
+ begin match prec with
+ | Empty -> h.data.(i) <- Empty
+ | Cons c -> c.next <- Empty
+ end
+ | (Cons ({key; data; next} as c)) as slot ->
+ begin match f key data with
+ | None ->
+ h.size <- h.size - 1;
+ filter_map_inplace_bucket f h i prec next
+ | Some data ->
+ begin match prec with
+ | Empty -> h.data.(i) <- slot
+ | Cons c -> c.next <- slot
+ end;
+ c.data <- data;
+ filter_map_inplace_bucket f h i slot next
+ end
+
let filter_map_inplace f h =
- let rec do_bucket = function
- | Empty ->
- Empty
- | Cons(k, d, rest) ->
- match f k d with
- | None -> h.size <- h.size - 1; do_bucket rest
- | Some new_d -> Cons(k, new_d, do_bucket rest)
- in
let d = h.data in
- for i = 0 to Array.length d - 1 do
- d.(i) <- do_bucket d.(i)
- done
+ let old_trav = ongoing_traversal h in
+ if not old_trav then flip_ongoing_traversal h;
+ try
+ for i = 0 to Array.length d - 1 do
+ filter_map_inplace_bucket f h i Empty h.data.(i)
+ done
+ with exn when not old_trav ->
+ flip_ongoing_traversal h;
+ raise exn
let fold f h init =
let rec do_bucket b accu =