talircd/lib/data/dllist.ml

102 lines
2.3 KiB
OCaml

(* This file was originally part of lwt-dllist, which is licensed
under MIT: https://github.com/ocsigen/lwt/blob/master/LICENSE.md. *)
type 'a t = {
mutable prev : 'a t;
mutable next : 'a t;
}
type 'a node = {
mutable node_prev : 'a t;
mutable node_next : 'a t;
mutable node_active : bool;
node_data : 'a;
}
(* XXX: technically [.node_next]/[.node_prev] *are* mutated in [remove] but they are [Obj.magic]'d
into ['a t] first.*)
[@@warning "-69"]
external seq_of_node : 'a node -> 'a t = "%identity"
external node_of_seq : 'a t -> 'a node = "%identity"
let create () =
let rec seq = { prev = seq; next = seq } in
seq
let is_empty seq = seq.next == seq
let remove node =
if node.node_active then begin
node.node_active <- false;
let seq = seq_of_node node in
seq.prev.next <- seq.next;
seq.next.prev <- seq.prev
end
let add_l data seq =
let node = { node_prev = seq; node_next = seq.next; node_data = data; node_active = true } in
seq.next.prev <- seq_of_node node;
seq.next <- seq_of_node node;
node
let add_r data seq =
let node = { node_prev = seq.prev; node_next = seq; node_data = data; node_active = true } in
seq.prev.next <- seq_of_node node;
seq.prev <- seq_of_node node;
node
let take_l seq =
if is_empty seq then raise Not_found;
begin
let node = node_of_seq seq.next in
remove node;
node.node_data
end
let take_r seq =
if is_empty seq then raise Not_found;
begin
let node = node_of_seq seq.prev in
remove node;
node.node_data
end
let fold_r f seq acc =
let rec loop curr acc =
if curr == seq then
acc
else
let node = node_of_seq curr in
if node.node_active then
loop node.node_prev (f node.node_data acc)
else
loop node.node_prev acc
in
loop seq.prev acc
let find f seq =
let rec loop curr =
if curr == seq then
raise Not_found
else
let node = node_of_seq curr in
if node.node_active && f node.node_data then
node.node_data
else
loop node.node_next
in
loop seq.next
let exists f seq =
let rec loop curr =
if curr == seq then
false
else
let node = node_of_seq curr in
if node.node_active && f node.node_data then
true
else
loop node.node_next
in
loop seq.next