Support an array that dynamically resizes itself, and replace usages of `List`, `Array`, and `Queue` with `Vec`. Change-Id: I910b140b7c1bdddae40e08f8191986dccbc6fddf Reviewed-on: https://cl.tvl.fyi/c/depot/+/7080 Tested-by: BuildkiteCI Reviewed-by: wpcarro <wpcarro@gmail.com>
		
			
				
	
	
		
			127 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			OCaml
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			OCaml
		
	
	
	
	
	
(****************************************************************************** 
 | 
						|
 * Similar to Python's list
 | 
						|
 *
 | 
						|
 * - mutable
 | 
						|
 * - dynamically resized
 | 
						|
 * - O(1) read
 | 
						|
 * - O(1) write
 | 
						|
 * - O(1) append (average case)
 | 
						|
 *
 | 
						|
 ******************************************************************************)
 | 
						|
 | 
						|
type 'a vec = {
 | 
						|
  mutable length: int;
 | 
						|
  mutable capacity: int;
 | 
						|
  mutable xs: 'a array;
 | 
						|
}
 | 
						|
 | 
						|
(****************************************************************************** 
 | 
						|
 * Constructors
 | 
						|
 ******************************************************************************)
 | 
						|
 | 
						|
let make (size : int) (seed : 'a) : 'a vec = { 
 | 
						|
  length = size;
 | 
						|
  capacity = size;
 | 
						|
  xs = Array.make size seed;
 | 
						|
}
 | 
						|
 | 
						|
let create () = {
 | 
						|
  length = 0;
 | 
						|
  capacity = 0;
 | 
						|
  xs = [||];
 | 
						|
}
 | 
						|
 | 
						|
let from_array (xs : 'a array) : 'a vec = {
 | 
						|
  length = Array.length xs;
 | 
						|
  capacity = Array.length xs;
 | 
						|
  xs = xs;
 | 
						|
}
 | 
						|
 | 
						|
let from_list (xs : 'a list) : 'a vec = 
 | 
						|
  match xs with
 | 
						|
  | [] -> create ()
 | 
						|
  | y::ys -> 
 | 
						|
    let result = {
 | 
						|
      length = List.length xs;
 | 
						|
      capacity = List.length xs;
 | 
						|
      xs = Array.make (List.length xs) y;
 | 
						|
    } in
 | 
						|
    List.iteri (fun i x -> Array.set result.xs i x) xs;
 | 
						|
    result
 | 
						|
 | 
						|
(****************************************************************************** 
 | 
						|
 * Miscellaneous
 | 
						|
 ******************************************************************************)
 | 
						|
 | 
						|
let append (x : 'a) (v : 'a vec) =
 | 
						|
  if v.capacity = 0 then
 | 
						|
    begin
 | 
						|
      v.length <- 1;
 | 
						|
      v.capacity <- 1;
 | 
						|
      v.xs <- [|x|];
 | 
						|
    end
 | 
						|
  else if v.length = v.capacity then
 | 
						|
    begin
 | 
						|
      (* According to Wikipedia, Python uses 1.25 as the growth factor *)
 | 
						|
      let new_cap = v.capacity |> float_of_int |> Float.mul 1.25 |> ceil |> int_of_float in
 | 
						|
      let new_xs = Array.make new_cap x in
 | 
						|
      Array.iteri (fun i x -> Array.set new_xs i x) v.xs;
 | 
						|
      v.capacity <- new_cap;
 | 
						|
      v.xs <- new_xs;
 | 
						|
      Array.set v.xs v.length x;
 | 
						|
      v.length <- v.length + 1;
 | 
						|
    end
 | 
						|
  else
 | 
						|
    begin
 | 
						|
      Array.set v.xs v.length x;
 | 
						|
      v.length <- v.length + 1;
 | 
						|
    end
 | 
						|
 | 
						|
let get (i : int) (v : 'a vec) : 'a option =
 | 
						|
  if i >= v.length then
 | 
						|
    None
 | 
						|
  else
 | 
						|
    Some v.xs.(i)
 | 
						|
 | 
						|
let get_unsafe (i : int) (v : 'a vec) : 'a =
 | 
						|
  v.xs.(i)
 | 
						|
 | 
						|
let set (i : int) (x : 'a) (v : 'a vec) : unit =
 | 
						|
  if i < v.length then
 | 
						|
    Array.set v.xs i x
 | 
						|
 | 
						|
let length (v : 'a vec) : int = 
 | 
						|
  v.length
 | 
						|
 | 
						|
let update (i : int) (f : 'a -> 'a) (v : 'a vec) : unit =
 | 
						|
  match get i v with
 | 
						|
  | None -> ()
 | 
						|
  | Some x -> set i (f x) v
 | 
						|
 | 
						|
let iter (f : 'a -> unit) (v : 'a vec) : unit =
 | 
						|
  let n = ref 0 in
 | 
						|
  while !n < v.length do
 | 
						|
    f v.xs.(!n);
 | 
						|
    n := !n + 1;
 | 
						|
  done
 | 
						|
 | 
						|
let join (sep : string) (v : string vec) : string =
 | 
						|
  if length v = 0 then
 | 
						|
    ""
 | 
						|
  else
 | 
						|
    let i = ref 1 in
 | 
						|
    let result = ref v.xs.(0) in
 | 
						|
    while !i < v.length do
 | 
						|
      result := !result ^ sep ^ v.xs.(!i);
 | 
						|
      i := !i + 1;
 | 
						|
    done;
 | 
						|
    !result
 | 
						|
 | 
						|
let map (f : 'a -> 'b) (v : 'a vec) : 'b vec =
 | 
						|
  let result = create () in
 | 
						|
  iter (fun x -> append (f x) result) v;
 | 
						|
  result
 | 
						|
 | 
						|
let append_to (dst : 'a vec) (xs : 'a vec) : unit =
 | 
						|
  iter (fun x -> append x dst) xs
 | 
						|
 |