(**************************************************************************) (* *) (* OCaml *) (* *) (* Francois Pottier, projet Cristal, INRIA Rocquencourt *) (* Jeremie Dimino, Jane Street Europe *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) exception Empty type 'a cell = | Nil | Cons of { content: 'a; mutable next: 'a cell } type 'a t = { mutable length: int; mutable first: 'a cell; mutable last: 'a cell } let create () = { length = 0; first = Nil; last = Nil } let clear q = q.length <- 0; q.first <- Nil; q.last <- Nil let add x q = let cell = Cons { content = x; next = Nil } in match q.last with | Nil -> q.length <- 1; q.first <- cell; q.last <- cell | Cons last -> q.length <- q.length + 1; last.next <- cell; q.last <- cell let push = add let peek q = match q.first with | Nil -> raise Empty | Cons { content } -> content let peek_opt q = match q.first with | Nil -> None | Cons { content } -> Some content let top = peek let take q = match q.first with | Nil -> raise Empty | Cons { content; next = Nil } -> clear q; content | Cons { content; next } -> q.length <- q.length - 1; q.first <- next; content let take_opt q = match q.first with | Nil -> None | Cons { content; next = Nil } -> clear q; Some content | Cons { content; next } -> q.length <- q.length - 1; q.first <- next; Some content let pop = take let copy = let rec copy q_res prev cell = match cell with | Nil -> q_res.last <- prev; q_res | Cons { content; next } -> let res = Cons { content; next = Nil } in begin match prev with | Nil -> q_res.first <- res | Cons p -> p.next <- res end; copy q_res res next in fun q -> copy { length = q.length; first = Nil; last = Nil } Nil q.first let is_empty q = q.length = 0 let length q = q.length let iter = let rec iter f cell = match cell with | Nil -> () | Cons { content; next } -> f content; iter f next in fun f q -> iter f q.first let fold = let rec fold f accu cell = match cell with | Nil -> accu | Cons { content; next } -> let accu = f accu content in fold f accu next in fun f accu q -> fold f accu q.first let transfer q1 q2 = if q1.length > 0 then match q2.last with | Nil -> q2.length <- q1.length; q2.first <- q1.first; q2.last <- q1.last; clear q1 | Cons last -> q2.length <- q2.length + q1.length; last.next <- q1.first; q2.last <- q1.last; clear q1 (** {1 Iterators} *) let to_seq q = let rec aux c () = match c with | Nil -> Seq.Nil | Cons { content=x; next; } -> Seq.Cons (x, aux next) in aux q.first let add_seq q i = Seq.iter (fun x -> push x q) i let of_seq g = let q = create() in add_seq q g; q