mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
bounded/unbounded versions of blit_from
This commit is contained in:
parent
2cf485ebee
commit
a43145b107
2 changed files with 56 additions and 19 deletions
|
|
@ -26,15 +26,17 @@ type 'a t = {
|
||||||
mutable start : int;
|
mutable start : int;
|
||||||
mutable stop : int; (* excluded *)
|
mutable stop : int; (* excluded *)
|
||||||
mutable buf : 'a array;
|
mutable buf : 'a array;
|
||||||
max_capacity: int
|
bounded : bool;
|
||||||
|
size : int
|
||||||
}
|
}
|
||||||
|
|
||||||
exception Empty
|
exception Empty
|
||||||
|
|
||||||
let create ?(max_capacity=max_int) () =
|
let create ?(bounded=false) size =
|
||||||
{ start=0;
|
{ start=0;
|
||||||
stop=0;
|
stop=0;
|
||||||
max_capacity;
|
bounded;
|
||||||
|
size;
|
||||||
buf = Array.of_list []
|
buf = Array.of_list []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +46,7 @@ let copy b =
|
||||||
|
|
||||||
let capacity b = Array.length b.buf
|
let capacity b = Array.length b.buf
|
||||||
|
|
||||||
let max_capacity b = b.max_capacity
|
let max_capacity b = if b.bounded then Some b.size else None
|
||||||
|
|
||||||
let length b =
|
let length b =
|
||||||
if b.stop >= b.start
|
if b.stop >= b.start
|
||||||
|
|
@ -70,22 +72,56 @@ let resize b cap elem =
|
||||||
in
|
in
|
||||||
b.buf <- buf'
|
b.buf <- buf'
|
||||||
|
|
||||||
let blit_from b from_buf o len =
|
let blit_from_bounded b from_buf o len =
|
||||||
if (Array.length from_buf) = 0 then () else
|
let cap = capacity b - len in
|
||||||
let cap = capacity b - length b in
|
|
||||||
(* resize if needed, with a constant to amortize *)
|
(* resize if needed, with a constant to amortize *)
|
||||||
if cap < len then
|
if cap < len then
|
||||||
resize b (min (b.max_capacity+1) (Array.length b.buf + len + 24)) from_buf.(0);
|
let new_size =
|
||||||
|
let desired = Array.length b.buf + len + 24 in
|
||||||
|
min (b.size+1) desired in
|
||||||
|
resize b new_size from_buf.(0);
|
||||||
let sub = Array.sub from_buf o len in
|
let sub = Array.sub from_buf o len in
|
||||||
|
let capacity = capacity b in
|
||||||
let iter x =
|
let iter x =
|
||||||
if b.start = 0 then b.start <- capacity b - 1 else b.start <- b.start - 1;
|
Array.set b.buf b.stop x;
|
||||||
|
if b.stop = capacity-1 then b.stop <- 0 else b.stop <- b.stop + 1;
|
||||||
if b.start = b.stop then
|
if b.start = b.stop then
|
||||||
begin
|
begin
|
||||||
if b.stop = 0 then b.stop <- capacity b - 1 else b.stop <- b.stop - 1
|
if b.start = capacity-1 then b.start <- 0 else b.start <- b.start + 1
|
||||||
end;
|
end
|
||||||
Array.set b.buf b.start x in
|
in
|
||||||
Array.iter iter sub
|
Array.iter iter sub
|
||||||
|
|
||||||
|
|
||||||
|
let blit_from_unbounded b from_buf o len =
|
||||||
|
let cap = capacity b - len in
|
||||||
|
(* resize if needed, with a constant to amortize *)
|
||||||
|
if cap < len then resize b (max b.size (Array.length b.buf + len + 24)) from_buf.(0);
|
||||||
|
assert (capacity b - length b >= len);
|
||||||
|
if b.stop >= b.start
|
||||||
|
then (* [_______ start xxxxxxxxx stop ______] *)
|
||||||
|
let len_end = Array.length b.buf - b.stop in
|
||||||
|
if len_end >= len
|
||||||
|
then (Array.blit from_buf o b.buf b.stop len;
|
||||||
|
b.stop <- b.stop + len)
|
||||||
|
else (Array.blit from_buf o b.buf b.stop len_end;
|
||||||
|
Array.blit from_buf (o+len_end) b.buf 0 (len-len_end);
|
||||||
|
b.stop <- len-len_end)
|
||||||
|
else begin (* [xxxxx stop ____________ start xxxxxx] *)
|
||||||
|
let len_middle = b.start - b.stop in
|
||||||
|
assert (len_middle >= len);
|
||||||
|
Array.blit from_buf o b.buf b.stop len;
|
||||||
|
b.stop <- b.stop + len
|
||||||
|
end;
|
||||||
|
()
|
||||||
|
|
||||||
|
let blit_from b from_buf o len =
|
||||||
|
if (Array.length from_buf) = 0 then () else
|
||||||
|
if b.bounded then
|
||||||
|
blit_from_bounded b from_buf o len
|
||||||
|
else
|
||||||
|
blit_from_unbounded b from_buf o len
|
||||||
|
|
||||||
let blit_into b to_buf o len =
|
let blit_into b to_buf o len =
|
||||||
if o+len > Array.length to_buf
|
if o+len > Array.length to_buf
|
||||||
then raise (Invalid_argument "BufferIO.blit_into");
|
then raise (Invalid_argument "BufferIO.blit_into");
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,15 @@ type 'a t = private {
|
||||||
mutable start : int;
|
mutable start : int;
|
||||||
mutable stop : int; (* excluded *)
|
mutable stop : int; (* excluded *)
|
||||||
mutable buf : 'a array;
|
mutable buf : 'a array;
|
||||||
max_capacity : int
|
bounded: bool;
|
||||||
|
size : int
|
||||||
}
|
}
|
||||||
|
|
||||||
exception Empty
|
exception Empty
|
||||||
|
|
||||||
val create : ?max_capacity:int -> unit -> 'a t
|
val create : ?bounded:bool -> int -> 'a t
|
||||||
(** [create ~max_capacity ()] creates a new buffer with given maximum capacity.
|
(** [create ?bounded size] creates a new buffer with given size.
|
||||||
Defaults to unbounded. *)
|
Defaults to [bounded=false]. *)
|
||||||
|
|
||||||
val copy : 'a t ->'a t
|
val copy : 'a t ->'a t
|
||||||
(** fresh copy of the buffer *)
|
(** fresh copy of the buffer *)
|
||||||
|
|
@ -39,8 +40,8 @@ val copy : 'a t ->'a t
|
||||||
val capacity : 'a t -> int
|
val capacity : 'a t -> int
|
||||||
(** length of the inner buffer *)
|
(** length of the inner buffer *)
|
||||||
|
|
||||||
val max_capacity : 'a t -> int
|
val max_capacity : 'a t -> int option
|
||||||
(** maximum length of the inner buffer *)
|
(** maximum length of the inner buffer, or [None] if unbounded. *)
|
||||||
|
|
||||||
val length : 'a t -> int
|
val length : 'a t -> int
|
||||||
(** number of elements currently stored in the buffer *)
|
(** number of elements currently stored in the buffer *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue