|
rpm-build |
0f2925 |
(*
|
|
rpm-build |
0f2925 |
* Enum - Enumeration over abstract collection of elements.
|
|
rpm-build |
0f2925 |
* Copyright (C) 2003 Nicolas Cannasse
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is free software; you can redistribute it and/or
|
|
rpm-build |
0f2925 |
* modify it under the terms of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License as published by the Free Software Foundation; either
|
|
rpm-build |
0f2925 |
* version 2.1 of the License, or (at your option) any later version,
|
|
rpm-build |
0f2925 |
* with the special exception on linking described in file LICENSE.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is distributed in the hope that it will be useful,
|
|
rpm-build |
0f2925 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
0f2925 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
0f2925 |
* Lesser General Public License for more details.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* You should have received a copy of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License along with this library; if not, write to the Free Software
|
|
rpm-build |
0f2925 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
rpm-build |
0f2925 |
*)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type 'a t = {
|
|
rpm-build |
0f2925 |
mutable count : unit -> int;
|
|
rpm-build |
0f2925 |
mutable next : unit -> 'a;
|
|
rpm-build |
0f2925 |
mutable clone : unit -> 'a t;
|
|
rpm-build |
0f2925 |
mutable fast : bool;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
(* raised by 'next' functions, should NOT go outside the API *)
|
|
rpm-build |
0f2925 |
exception No_more_elements
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let _dummy () = assert false
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let make ~next ~count ~clone =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
count = count;
|
|
rpm-build |
0f2925 |
next = next;
|
|
rpm-build |
0f2925 |
clone = clone;
|
|
rpm-build |
0f2925 |
fast = true;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec init n f =
|
|
rpm-build |
0f2925 |
if n < 0 then invalid_arg "Enum.init";
|
|
rpm-build |
0f2925 |
let count = ref n in
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
count = (fun () -> !count);
|
|
rpm-build |
0f2925 |
next = (fun () ->
|
|
rpm-build |
0f2925 |
match !count with
|
|
rpm-build |
0f2925 |
| 0 -> raise No_more_elements
|
|
rpm-build |
0f2925 |
| _ ->
|
|
rpm-build |
0f2925 |
decr count;
|
|
rpm-build |
0f2925 |
f (n - 1 - !count));
|
|
rpm-build |
0f2925 |
clone = (fun () -> init !count f);
|
|
rpm-build |
0f2925 |
fast = true;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec empty () =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
count = (fun () -> 0);
|
|
rpm-build |
0f2925 |
next = (fun () -> raise No_more_elements);
|
|
rpm-build |
0f2925 |
clone = (fun () -> empty());
|
|
rpm-build |
0f2925 |
fast = true;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type 'a _mut_list = {
|
|
rpm-build |
0f2925 |
hd : 'a;
|
|
rpm-build |
0f2925 |
mutable tl : 'a _mut_list;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let force t =
|
|
rpm-build |
0f2925 |
let rec clone enum count =
|
|
rpm-build |
0f2925 |
let enum = ref !enum
|
|
rpm-build |
0f2925 |
and count = ref !count in
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
count = (fun () -> !count);
|
|
rpm-build |
0f2925 |
next = (fun () ->
|
|
rpm-build |
0f2925 |
match !enum with
|
|
rpm-build |
0f2925 |
| [] -> raise No_more_elements
|
|
rpm-build |
0f2925 |
| h :: t -> decr count; enum := t; h);
|
|
rpm-build |
0f2925 |
clone = (fun () ->
|
|
rpm-build |
0f2925 |
let enum = ref !enum
|
|
rpm-build |
0f2925 |
and count = ref !count in
|
|
rpm-build |
0f2925 |
clone enum count);
|
|
rpm-build |
0f2925 |
fast = true;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let count = ref 0 in
|
|
rpm-build |
0f2925 |
let _empty = Obj.magic [] in
|
|
rpm-build |
0f2925 |
let rec loop dst =
|
|
rpm-build |
0f2925 |
let x = { hd = t.next(); tl = _empty } in
|
|
rpm-build |
0f2925 |
incr count;
|
|
rpm-build |
0f2925 |
dst.tl <- x;
|
|
rpm-build |
0f2925 |
loop x
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let enum = ref _empty in
|
|
rpm-build |
0f2925 |
(try
|
|
rpm-build |
0f2925 |
enum := { hd = t.next(); tl = _empty };
|
|
rpm-build |
0f2925 |
incr count;
|
|
rpm-build |
0f2925 |
loop !enum;
|
|
rpm-build |
0f2925 |
with No_more_elements -> ());
|
|
rpm-build |
0f2925 |
let tc = clone (Obj.magic enum) count in
|
|
rpm-build |
0f2925 |
t.clone <- tc.clone;
|
|
rpm-build |
0f2925 |
t.next <- tc.next;
|
|
rpm-build |
0f2925 |
t.count <- tc.count;
|
|
rpm-build |
0f2925 |
t.fast <- true
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let from f =
|
|
rpm-build |
0f2925 |
let e = {
|
|
rpm-build |
0f2925 |
next = f;
|
|
rpm-build |
0f2925 |
count = _dummy;
|
|
rpm-build |
0f2925 |
clone = _dummy;
|
|
rpm-build |
0f2925 |
fast = false;
|
|
rpm-build |
0f2925 |
} in
|
|
rpm-build |
0f2925 |
e.count <- (fun () -> force e; e.count());
|
|
rpm-build |
0f2925 |
e.clone <- (fun () -> force e; e.clone());
|
|
rpm-build |
0f2925 |
e
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let from2 next clone =
|
|
rpm-build |
0f2925 |
let e = {
|
|
rpm-build |
0f2925 |
next = next;
|
|
rpm-build |
0f2925 |
count = _dummy;
|
|
rpm-build |
0f2925 |
clone = clone;
|
|
rpm-build |
0f2925 |
fast = false;
|
|
rpm-build |
0f2925 |
} in
|
|
rpm-build |
0f2925 |
e.count <- (fun () -> force e; e.count());
|
|
rpm-build |
0f2925 |
e
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let next t = t.next ()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let get t =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
Some (t.next())
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> None
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let push t e =
|
|
rpm-build |
0f2925 |
let rec make t =
|
|
rpm-build |
0f2925 |
let fnext = t.next in
|
|
rpm-build |
0f2925 |
let fcount = t.count in
|
|
rpm-build |
0f2925 |
let fclone = t.clone in
|
|
rpm-build |
0f2925 |
let next_called = ref false in
|
|
rpm-build |
0f2925 |
t.next <- (fun () ->
|
|
rpm-build |
0f2925 |
next_called := true;
|
|
rpm-build |
0f2925 |
t.next <- fnext;
|
|
rpm-build |
0f2925 |
t.count <- fcount;
|
|
rpm-build |
0f2925 |
t.clone <- fclone;
|
|
rpm-build |
0f2925 |
e);
|
|
rpm-build |
0f2925 |
t.count <- (fun () ->
|
|
rpm-build |
0f2925 |
let n = fcount() in
|
|
rpm-build |
0f2925 |
if !next_called then n else n+1);
|
|
rpm-build |
0f2925 |
t.clone <- (fun () ->
|
|
rpm-build |
0f2925 |
let tc = fclone() in
|
|
rpm-build |
0f2925 |
if not !next_called then make tc;
|
|
rpm-build |
0f2925 |
tc);
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
make t
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let peek t =
|
|
rpm-build |
0f2925 |
match get t with
|
|
rpm-build |
0f2925 |
| None -> None
|
|
rpm-build |
0f2925 |
| Some x ->
|
|
rpm-build |
0f2925 |
push t x;
|
|
rpm-build |
0f2925 |
Some x
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let junk t =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
ignore(t.next())
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> ()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let is_empty t =
|
|
rpm-build |
0f2925 |
if t.fast then
|
|
rpm-build |
0f2925 |
t.count() = 0
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
peek t = None
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let count t =
|
|
rpm-build |
0f2925 |
t.count()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let fast_count t =
|
|
rpm-build |
0f2925 |
t.fast
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let clone t =
|
|
rpm-build |
0f2925 |
t.clone()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let iter f t =
|
|
rpm-build |
0f2925 |
let rec loop () =
|
|
rpm-build |
0f2925 |
f (t.next());
|
|
rpm-build |
0f2925 |
loop();
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop();
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> ()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let iteri f t =
|
|
rpm-build |
0f2925 |
let rec loop idx =
|
|
rpm-build |
0f2925 |
f idx (t.next());
|
|
rpm-build |
0f2925 |
loop (idx+1);
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop 0;
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> ()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let iter2 f t u =
|
|
rpm-build |
0f2925 |
let push_t = ref None in
|
|
rpm-build |
0f2925 |
let rec loop () =
|
|
rpm-build |
0f2925 |
push_t := None;
|
|
rpm-build |
0f2925 |
let e = t.next() in
|
|
rpm-build |
0f2925 |
push_t := Some e;
|
|
rpm-build |
0f2925 |
f e (u.next());
|
|
rpm-build |
0f2925 |
loop ()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop ()
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements ->
|
|
rpm-build |
0f2925 |
match !push_t with
|
|
rpm-build |
0f2925 |
| None -> ()
|
|
rpm-build |
0f2925 |
| Some e ->
|
|
rpm-build |
0f2925 |
push t e
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let iter2i f t u =
|
|
rpm-build |
0f2925 |
let push_t = ref None in
|
|
rpm-build |
0f2925 |
let rec loop idx =
|
|
rpm-build |
0f2925 |
push_t := None;
|
|
rpm-build |
0f2925 |
let e = t.next() in
|
|
rpm-build |
0f2925 |
push_t := Some e;
|
|
rpm-build |
0f2925 |
f idx e (u.next());
|
|
rpm-build |
0f2925 |
loop (idx + 1)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop 0
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements ->
|
|
rpm-build |
0f2925 |
match !push_t with
|
|
rpm-build |
0f2925 |
| None -> ()
|
|
rpm-build |
0f2925 |
| Some e -> push t e
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let fold f init t =
|
|
rpm-build |
0f2925 |
let acc = ref init in
|
|
rpm-build |
0f2925 |
let rec loop() =
|
|
rpm-build |
0f2925 |
acc := f (t.next()) !acc;
|
|
rpm-build |
0f2925 |
loop()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop()
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> !acc
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let foldi f init t =
|
|
rpm-build |
0f2925 |
let acc = ref init in
|
|
rpm-build |
0f2925 |
let rec loop idx =
|
|
rpm-build |
0f2925 |
acc := f idx (t.next()) !acc;
|
|
rpm-build |
0f2925 |
loop (idx + 1)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop 0
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> !acc
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let fold2 f init t u =
|
|
rpm-build |
0f2925 |
let acc = ref init in
|
|
rpm-build |
0f2925 |
let push_t = ref None in
|
|
rpm-build |
0f2925 |
let rec loop() =
|
|
rpm-build |
0f2925 |
push_t := None;
|
|
rpm-build |
0f2925 |
let e = t.next() in
|
|
rpm-build |
0f2925 |
push_t := Some e;
|
|
rpm-build |
0f2925 |
acc := f e (u.next()) !acc;
|
|
rpm-build |
0f2925 |
loop()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop()
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements ->
|
|
rpm-build |
0f2925 |
match !push_t with
|
|
rpm-build |
0f2925 |
| None -> !acc
|
|
rpm-build |
0f2925 |
| Some e ->
|
|
rpm-build |
0f2925 |
push t e;
|
|
rpm-build |
0f2925 |
!acc
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let fold2i f init t u =
|
|
rpm-build |
0f2925 |
let acc = ref init in
|
|
rpm-build |
0f2925 |
let push_t = ref None in
|
|
rpm-build |
0f2925 |
let rec loop idx =
|
|
rpm-build |
0f2925 |
push_t := None;
|
|
rpm-build |
0f2925 |
let e = t.next() in
|
|
rpm-build |
0f2925 |
push_t := Some e;
|
|
rpm-build |
0f2925 |
acc := f idx e (u.next()) !acc;
|
|
rpm-build |
0f2925 |
loop (idx + 1)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop 0
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements ->
|
|
rpm-build |
0f2925 |
match !push_t with
|
|
rpm-build |
0f2925 |
| None -> !acc
|
|
rpm-build |
0f2925 |
| Some e ->
|
|
rpm-build |
0f2925 |
push t e;
|
|
rpm-build |
0f2925 |
!acc
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find f t =
|
|
rpm-build |
0f2925 |
let rec loop () =
|
|
rpm-build |
0f2925 |
let x = t.next() in
|
|
rpm-build |
0f2925 |
if f x then x else loop()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
loop()
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements -> raise Not_found
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec map f t =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
count = t.count;
|
|
rpm-build |
0f2925 |
next = (fun () -> f (t.next()));
|
|
rpm-build |
0f2925 |
clone = (fun () -> map f (t.clone()));
|
|
rpm-build |
0f2925 |
fast = t.fast;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec mapi f t =
|
|
rpm-build |
0f2925 |
let idx = ref (-1) in
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
count = t.count;
|
|
rpm-build |
0f2925 |
next = (fun () -> incr idx; f !idx (t.next()));
|
|
rpm-build |
0f2925 |
clone = (fun () -> mapi f (t.clone()));
|
|
rpm-build |
0f2925 |
fast = t.fast;
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec filter f t =
|
|
rpm-build |
0f2925 |
let rec next() =
|
|
rpm-build |
0f2925 |
let x = t.next() in
|
|
rpm-build |
0f2925 |
if f x then x else next()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
from2 next (fun () -> filter f (t.clone()))
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec filter_map f t =
|
|
rpm-build |
0f2925 |
let rec next () =
|
|
rpm-build |
0f2925 |
match f (t.next()) with
|
|
rpm-build |
0f2925 |
| None -> next()
|
|
rpm-build |
0f2925 |
| Some x -> x
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
from2 next (fun () -> filter_map f (t.clone()))
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec append ta tb =
|
|
rpm-build |
0f2925 |
let t = {
|
|
rpm-build |
0f2925 |
count = (fun () -> ta.count() + tb.count());
|
|
rpm-build |
0f2925 |
next = _dummy;
|
|
rpm-build |
0f2925 |
clone = (fun () -> append (ta.clone()) (tb.clone()));
|
|
rpm-build |
0f2925 |
fast = ta.fast && tb.fast;
|
|
rpm-build |
0f2925 |
} in
|
|
rpm-build |
0f2925 |
t.next <- (fun () ->
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
ta.next()
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements ->
|
|
rpm-build |
0f2925 |
(* add one indirection because tb can mute *)
|
|
rpm-build |
0f2925 |
t.next <- (fun () -> tb.next());
|
|
rpm-build |
0f2925 |
t.count <- (fun () -> tb.count());
|
|
rpm-build |
0f2925 |
t.clone <- (fun () -> tb.clone());
|
|
rpm-build |
0f2925 |
t.fast <- tb.fast;
|
|
rpm-build |
0f2925 |
t.next()
|
|
rpm-build |
0f2925 |
);
|
|
rpm-build |
0f2925 |
t
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let rec concat t =
|
|
rpm-build |
0f2925 |
let concat_ref = ref _dummy in
|
|
rpm-build |
0f2925 |
let rec concat_next() =
|
|
rpm-build |
0f2925 |
let tn = t.next() in
|
|
rpm-build |
0f2925 |
concat_ref := (fun () ->
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
tn.next()
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
No_more_elements ->
|
|
rpm-build |
0f2925 |
concat_next());
|
|
rpm-build |
0f2925 |
!concat_ref ()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
concat_ref := concat_next;
|
|
rpm-build |
0f2925 |
from2 (fun () -> !concat_ref ()) (fun () -> concat (t.clone()))
|