063ab15d1dd9569b616a68d112c77a5b4b02c580
2 * Enum - Enumeration over abstract collection of elements.
3 * Copyright (C) 2003 Nicolas Cannasse
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version,
9 * with the special exception on linking described in file LICENSE.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 mutable count
: unit -> int;
23 mutable next
: unit -> 'a
;
24 mutable clone
: unit -> 'a t
;
28 (* raised by 'next' functions, should NOT go outside the API *)
29 exception No_more_elements
31 let _dummy () = assert false
33 let make ~next ~count ~clone
=
42 if n
< 0 then invalid_arg
"Enum.init";
45 count = (fun () -> !count);
48 | 0 -> raise No_more_elements
52 clone
= (fun () -> init !count f
);
58 count = (fun () -> 0);
59 next
= (fun () -> raise No_more_elements
);
60 clone
= (fun () -> empty());
66 mutable tl
: 'a _mut_list
;
70 let rec clone enum
count =
72 and count = ref !count in
74 count = (fun () -> !count);
77 | [] -> raise No_more_elements
78 | h
:: t
-> decr
count; enum := t
; h
);
81 and count = ref !count in
87 let _empty = Obj.magic
[] in
89 let x = { hd
= t
.next
(); tl
= _empty } in
94 let enum = ref _empty in
96 enum := { hd
= t
.next
(); tl
= _empty };
99 with No_more_elements
-> ());
100 let tc = clone (Obj.magic
enum) count in
113 e.count <- (fun () -> force e; e.count());
114 e.clone <- (fun () -> force e; e.clone());
117 let from2 next
clone =
124 e.count <- (fun () -> force e; e.count());
131 No_more_elements
-> None
135 let fnext = t
.next
in
136 let fcount = t
.count in
137 let fclone = t
.clone in
138 let next_called = ref false in
145 t
.count <- (fun () ->
147 if !next_called then n else n+1);
148 t
.clone <- (fun () ->
150 if not
!next_called then make tc;
166 No_more_elements
-> ()
191 No_more_elements
-> ()
201 No_more_elements
-> ()
204 let push_t = ref None
in
222 let push_t = ref None
in
239 let acc = ref init in
241 acc := f
(t
.next
()) !acc;
247 No_more_elements
-> !acc
250 let acc = ref init in
252 acc := f idx
(t
.next
()) !acc;
258 No_more_elements
-> !acc
260 let fold2 f
init t u
=
261 let acc = ref init in
262 let push_t = ref None
in
267 acc := f
e (u
.next
()) !acc;
280 let fold2i f
init t u
=
281 let acc = ref init in
282 let push_t = ref None
in
287 acc := f idx
e (u
.next
()) !acc;
303 if f
x then x else loop()
308 No_more_elements
-> raise Not_found
313 next
= (fun () -> f
(t
.next
()));
314 clone = (fun () -> map f
(t
.clone()));
319 let idx = ref (-1) in
322 next
= (fun () -> incr
idx; f
!idx (t
.next
()));
323 clone = (fun () -> mapi f
(t
.clone()));
330 if f
x then x else next()
332 from2 next (fun () -> filter f
(t
.clone()))
334 let rec filter_map f t
=
336 match f
(t
.next()) with
340 from2 next (fun () -> filter_map f
(t
.clone()))
342 let rec append ta tb
=
344 count = (fun () -> ta
.count() + tb
.count());
346 clone = (fun () -> append (ta
.clone()) (tb
.clone()));
347 fast
= ta
.fast
&& tb
.fast
;
354 (* add one indirection because tb can mute *)
355 t.next <- (fun () -> tb
.next());
356 t.count <- (fun () -> tb
.count());
357 t.clone <- (fun () -> tb
.clone());
364 let concat_ref = ref _dummy in
365 let rec concat_next() =
367 concat_ref := (fun () ->
375 concat_ref := concat_next;
376 from2 (fun () -> !concat_ref ()) (fun () -> concat (t.clone()))