From 98fd45ab9f7eda1823df3127856eee3dc85dc72e Mon Sep 17 00:00:00 2001 From: Vincent Bernardoff Date: Sat, 14 Jan 2017 13:13:19 +0100 Subject: [PATCH] Shell: add `Ring` --- src/Makefile | 2 ++ src/utils/ring.ml | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/utils/ring.mli | 20 ++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 src/utils/ring.ml create mode 100644 src/utils/ring.mli diff --git a/src/Makefile b/src/Makefile index 5f3fa9440..2bbba54b5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -163,6 +163,7 @@ UTILS_LIB_INTFS := \ utils/lwt_pipe.mli \ utils/IO.mli \ utils/moving_average.mli \ + utils/ring.mli \ UTILS_LIB_IMPLS := \ utils/base48.ml \ @@ -179,6 +180,7 @@ UTILS_LIB_IMPLS := \ utils/lwt_pipe.ml \ utils/IO.ml \ utils/moving_average.ml \ + utils/ring.ml \ UTILS_PACKAGES := \ ${MINUTILS_PACKAGES} \ diff --git a/src/utils/ring.ml b/src/utils/ring.ml new file mode 100644 index 000000000..7c829622e --- /dev/null +++ b/src/utils/ring.ml @@ -0,0 +1,59 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2016. *) +(* Dynamic Ledger Solutions, Inc. *) +(* *) +(* All rights reserved. No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +type 'a raw = + | Empty of int + | Inited of { + data : 'a array ; + mutable pos : int ; + } + +type 'a t = 'a raw ref + +let create size = ref (Empty size) + +let add r v = + match !r with + | Empty size -> + r := Inited { data = Array.make size v ; pos = 0 } + | Inited s -> + s.pos <- + if s.pos = 2 * Array.length s.data - 1 then + Array.length s.data + else + s.pos + 1 ; + s.data.(s.pos mod Array.length s.data) <- v + +let add_list r l = List.iter (add r) l + +let last r = + match !r with + | Empty _ -> None + | Inited { data ; pos } -> Some data.(pos mod Array.length data) + +let fold r ~init ~f = + match !r with + | Empty _ -> init + | Inited { data ; pos } -> + let size = Array.length data in + let acc = ref init in + for i = 0 to min pos (size - 1) do + acc := f !acc data.((pos - i) mod size) + done ; + !acc + +let elements t = + fold t ~init:[] ~f:(fun acc elt -> elt :: acc) + +exception Empty + +let last_exn r = + match last r with + | None -> raise Empty + | Some d -> d diff --git a/src/utils/ring.mli b/src/utils/ring.mli new file mode 100644 index 000000000..fe1b71b51 --- /dev/null +++ b/src/utils/ring.mli @@ -0,0 +1,20 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2016. *) +(* Dynamic Ledger Solutions, Inc. *) +(* *) +(* All rights reserved. No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +(** Imperative Ring Buffer *) + +type 'a t +val create : int -> 'a t +val add : 'a t -> 'a -> unit +val add_list : 'a t -> 'a list -> unit +val last : 'a t -> 'a option +exception Empty +val last_exn : 'a t -> 'a +val fold : 'a t -> init:'b -> f:('b -> 'a -> 'b) -> 'b +val elements : 'a t -> 'a list