vendored lwt-dllist, moved data structures to separate library
This commit is contained in:
parent
47185c83e1
commit
484941c3ce
|
@ -1,7 +1,3 @@
|
||||||
open! Import
|
|
||||||
|
|
||||||
include (val Logging.sublogs logger "Wheel")
|
|
||||||
|
|
||||||
type ('k, 'v) t = {
|
type ('k, 'v) t = {
|
||||||
mutable index : int;
|
mutable index : int;
|
||||||
entries : ('k, 'v) entry array;
|
entries : ('k, 'v) entry array;
|
|
@ -0,0 +1,101 @@
|
||||||
|
(* 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
|
|
@ -0,0 +1,66 @@
|
||||||
|
(* 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
|
||||||
|
(** Type of a sequence holding values of type ['a] *)
|
||||||
|
|
||||||
|
type 'a node
|
||||||
|
(** Type of a node holding one value of type ['a] in a sequence *)
|
||||||
|
|
||||||
|
(** {2 Operation on nodes} *)
|
||||||
|
|
||||||
|
val remove : 'a node -> unit
|
||||||
|
(** Removes a node from the sequence it is part of. It does nothing
|
||||||
|
if the node has already been removed. *)
|
||||||
|
|
||||||
|
(** {2 Operations on sequence} *)
|
||||||
|
|
||||||
|
val create : unit -> 'a t
|
||||||
|
(** [create ()] creates a new empty sequence *)
|
||||||
|
|
||||||
|
val is_empty : 'a t -> bool
|
||||||
|
(** Returns [true] iff the given sequence is empty *)
|
||||||
|
|
||||||
|
val add_l : 'a -> 'a t -> 'a node
|
||||||
|
(** [add_l x s] adds [x] to the left of the sequence [s] *)
|
||||||
|
|
||||||
|
val add_r : 'a -> 'a t -> 'a node
|
||||||
|
(** [add_r x s] adds [x] to the right of the sequence [s] *)
|
||||||
|
|
||||||
|
val take_l : 'a t -> 'a
|
||||||
|
(** [take_l x s] removes and returns the leftmost element of [s]
|
||||||
|
|
||||||
|
@raise Not_found if the sequence is empty *)
|
||||||
|
|
||||||
|
val take_r : 'a t -> 'a
|
||||||
|
(** [take_l x s] removes and returns the rightmost element of [s]
|
||||||
|
|
||||||
|
@raise Not_found if the sequence is empty *)
|
||||||
|
|
||||||
|
(** {2 Sequence iterators} *)
|
||||||
|
|
||||||
|
(** Note: it is OK to remove a node while traversing a sequence *)
|
||||||
|
|
||||||
|
(* val fold_l : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b *)
|
||||||
|
(* (\** [fold_l f s] is: *)
|
||||||
|
(* {[ *)
|
||||||
|
(* fold_l f s x = f en (... (f e2 (f e1 x))) *)
|
||||||
|
(* ]} *)
|
||||||
|
(* where [e1], [e2], ..., [en] are the elements of [s] *)
|
||||||
|
(* *\) *)
|
||||||
|
|
||||||
|
val fold_r : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
|
||||||
|
(** [fold_r f s] is:
|
||||||
|
{[
|
||||||
|
fold_r f s x = f e1 (f e2 (... (f en x)))
|
||||||
|
]}
|
||||||
|
where [e1], [e2], ..., [en] are the elements of [s]
|
||||||
|
*)
|
||||||
|
|
||||||
|
val find : ('a -> bool) -> 'a t -> 'a
|
||||||
|
(** [find_node_l f s] returns the first element of [s] starting from the left
|
||||||
|
that satisfies [f] or raises [Not_found] if none exists. *)
|
||||||
|
|
||||||
|
val exists : ('a -> bool) -> 'a t -> bool
|
||||||
|
(** [find_node_l f s] returns [true] if some node [s] starting from the left
|
||||||
|
that satisfies [f] or returns [false] if none exists. *)
|
|
@ -0,0 +1,5 @@
|
||||||
|
(library
|
||||||
|
(package talircd)
|
||||||
|
(name data)
|
||||||
|
(inline_tests)
|
||||||
|
(preprocess (pps ppx_expect)))
|
|
@ -0,0 +1,21 @@
|
||||||
|
include Stdlib.List
|
||||||
|
|
||||||
|
let flat_map f xs =
|
||||||
|
let rec iter = function
|
||||||
|
| [] -> []
|
||||||
|
| x :: xs -> append_then_iter xs (f x)
|
||||||
|
[@@tail_mod_cons]
|
||||||
|
and append_then_iter xs = function
|
||||||
|
| [] -> iter xs
|
||||||
|
| y :: ys -> y :: append_then_iter xs ys
|
||||||
|
[@@tail_mod_cons]
|
||||||
|
in
|
||||||
|
iter xs
|
||||||
|
|
||||||
|
let iter_up_to f xs ~limit =
|
||||||
|
let rec iter n = function
|
||||||
|
| x :: xs when n > 0 ->
|
||||||
|
f x; iter (n - 1) xs
|
||||||
|
| _ -> ()
|
||||||
|
in
|
||||||
|
iter limit xs
|
|
@ -1,5 +1,3 @@
|
||||||
open Import
|
|
||||||
|
|
||||||
let%expect_test _ =
|
let%expect_test _ =
|
||||||
let print_list print_ele xs =
|
let print_list print_ele xs =
|
||||||
let rec iter pre post = function
|
let rec iter pre post = function
|
|
@ -1,7 +1,3 @@
|
||||||
open Import
|
|
||||||
|
|
||||||
include (val Logging.sublogs logger "Wheel")
|
|
||||||
|
|
||||||
type 'a t = {
|
type 'a t = {
|
||||||
entries : 'a Dllist.t array;
|
entries : 'a Dllist.t array;
|
||||||
mutable index : int;
|
mutable index : int;
|
||||||
|
@ -21,7 +17,7 @@ let add t v =
|
||||||
let[@tail_mod_cons] rec empty t =
|
let[@tail_mod_cons] rec empty t =
|
||||||
match Dllist.take_l (queue t) with
|
match Dllist.take_l (queue t) with
|
||||||
| x -> x :: empty t
|
| x -> x :: empty t
|
||||||
| exception Dllist.Empty -> []
|
| exception Not_found -> []
|
||||||
|
|
||||||
let tick t =
|
let tick t =
|
||||||
t.index <- (t.index + 1) mod Array.length t.entries;
|
t.index <- (t.index + 1) mod Array.length t.entries;
|
|
@ -2,7 +2,7 @@
|
||||||
(package talircd)
|
(package talircd)
|
||||||
(name server)
|
(name server)
|
||||||
(libraries
|
(libraries
|
||||||
lwt lwt.unix lwt-dllist fmt
|
lwt lwt.unix fmt
|
||||||
logging irc)
|
logging irc data)
|
||||||
(inline_tests)
|
(inline_tests)
|
||||||
(preprocess (pps ppx_expect)))
|
(preprocess (pps ppx_expect)))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
include Data
|
||||||
include Irc
|
include Irc
|
||||||
module Dllist = Lwt_dllist
|
|
||||||
|
|
||||||
type sockaddr = Unix.sockaddr
|
type sockaddr = Unix.sockaddr
|
||||||
type fd = Lwt_unix.file_descr
|
type fd = Lwt_unix.file_descr
|
||||||
|
@ -16,28 +16,4 @@ module Result_syntax = struct
|
||||||
let ( let+ ) r f = Result.map f r
|
let ( let+ ) r f = Result.map f r
|
||||||
end
|
end
|
||||||
|
|
||||||
module List = struct
|
|
||||||
include List
|
|
||||||
|
|
||||||
let flat_map f xs =
|
|
||||||
let rec iter = function
|
|
||||||
| [] -> []
|
|
||||||
| x :: xs -> append_then_iter xs (f x)
|
|
||||||
[@@tail_mod_cons]
|
|
||||||
and append_then_iter xs = function
|
|
||||||
| [] -> iter xs
|
|
||||||
| y :: ys -> y :: append_then_iter xs ys
|
|
||||||
[@@tail_mod_cons]
|
|
||||||
in
|
|
||||||
iter xs
|
|
||||||
|
|
||||||
let iter_up_to f xs ~limit =
|
|
||||||
let rec iter n = function
|
|
||||||
| x :: xs when n > 0 ->
|
|
||||||
f x; iter (n - 1) xs
|
|
||||||
| _ -> ()
|
|
||||||
in
|
|
||||||
iter limit xs
|
|
||||||
end
|
|
||||||
|
|
||||||
include (val Logging.logs "Irc")
|
include (val Logging.logs "Irc")
|
||||||
|
|
|
@ -36,5 +36,5 @@ module Bcc = struct
|
||||||
let rec send_all msg =
|
let rec send_all msg =
|
||||||
match Dllist.take_l _recipients with
|
match Dllist.take_l _recipients with
|
||||||
| obx -> obx.bcc_incl <- false; send obx msg; send_all msg
|
| obx -> obx.bcc_incl <- false; send obx msg; send_all msg
|
||||||
| exception Dllist.Empty -> ()
|
| exception Not_found -> ()
|
||||||
end
|
end
|
||||||
|
|
|
@ -57,8 +57,8 @@ let join chan user =
|
||||||
end
|
end
|
||||||
|
|
||||||
let membership chan user =
|
let membership chan user =
|
||||||
Dllist.find_node_l (fun mem -> mem.mem_chan == chan)
|
Dllist.find (fun mem -> mem.mem_chan == chan)
|
||||||
user.membership |> Dllist.get
|
user.membership
|
||||||
|
|
||||||
let part mem =
|
let part mem =
|
||||||
try
|
try
|
||||||
|
|
|
@ -46,19 +46,12 @@ let channels t =
|
||||||
Dllist.fold_r (fun m xs -> m.mem_chan :: xs) t.membership []
|
Dllist.fold_r (fun m xs -> m.mem_chan :: xs) t.membership []
|
||||||
|
|
||||||
let highest_membership_priv t =
|
let highest_membership_priv t =
|
||||||
Dllist.fold_l (fun m p -> max m.mem_priv p) t.membership Normal
|
Dllist.fold_r (fun m p -> max m.mem_priv p) t.membership Normal
|
||||||
|
|
||||||
let is_member t chan =
|
let is_member t chan =
|
||||||
try
|
Dllist.exists (fun m -> m.mem_chan == chan)
|
||||||
Dllist.find_node_l (fun m -> m.mem_chan == chan)
|
t.membership
|
||||||
t.membership |> ignore;
|
|
||||||
true
|
|
||||||
with Not_found ->
|
|
||||||
false
|
|
||||||
|
|
||||||
let find_common_channel t1 t2 =
|
let find_common_channel t1 t2 =
|
||||||
let node =
|
let mem = Dllist.find (fun m -> is_member t2 m.mem_chan) t1.membership in
|
||||||
Dllist.find_node_l (fun m -> is_member t2 m.mem_chan)
|
mem.mem_chan
|
||||||
t1.membership
|
|
||||||
in
|
|
||||||
(Dllist.get node).mem_chan
|
|
||||||
|
|
Loading…
Reference in New Issue