1 (***********************************************************************)
5 (* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1997 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the GNU Library General Public License, with *)
10 (* the special exception on linking described in file ../LICENSE. *)
12 (***********************************************************************)
16 (* The fields of type t are not mutable to preserve polymorphism of
17 the empty stream. This is type safe because the empty stream is never
20 type 'a t
= { count
: int; data
: 'a data
}
23 | Scons
of 'a
* 'a data
24 | Sapp
of 'a data
* 'a data
25 | Slazy
of (unit -> 'a data
)
28 and 'a gen
= { mutable curr
: 'a
option option; func
: int -> 'a
option }
30 { ic
: in_channel
; buff
: string; mutable len
: int; mutable ind
: int }
33 exception Error
of string;;
35 external count
: 'a t
-> int = "%field0";;
36 external set_count
: 'a t
-> int -> unit = "%setfield0";;
37 let set_data (s
: 'a t
) (d
: 'a data
) =
38 Obj.set_field
(Obj.repr s
) 1 (Obj.repr d
)
42 b
.len
<- input b
.ic b
.buff
0 (String.length b
.buff
); b
.ind
<- 0
48 | Scons
(a
, d
) -> Some
(a
, d
)
50 begin match get_data d1
with
51 Some
(a
, d1
) -> Some
(a
, Sapp
(d1
, d2
))
56 Sgen _
| Sbuffio _
-> failwith
"illegal stream concatenation"
59 | Sgen _
| Sbuffio _
->
60 failwith
"illegal stream concatenation"
66 | Scons
(a
, _
) -> Some a
68 begin match get_data s
.data
with
69 Some
(a
, d
) -> set_data s
(Scons
(a
, d
)); Some a
74 Sgen _
| Sbuffio _
-> failwith
"illegal stream concatenation"
75 | d
-> set_data s d
; peek s
77 | Sgen
{curr
= Some a
} -> a
78 | Sgen g
-> let x = g
.func s
.count
in g
.curr
<- Some
x; x
80 if b
.ind
>= b
.len
then fill_buff b
;
81 if b
.len
== 0 then begin set_data s Sempty
; None
end
82 else Some
(Obj.magic
(String.unsafe_get b
.buff b
.ind
))
87 Scons
(_
, d
) -> set_count s
(succ s
.count
); set_data s d
88 | Sgen
({curr
= Some _
} as g
) -> set_count s
(succ s
.count
); g
.curr
<- None
89 | Sbuffio b
-> set_count s
(succ s
.count
); b
.ind
<- succ b
.ind
97 if n
<= 0 then [], s
.data
, 0
102 let (al
, d
, k
) = nget (pred n
) s
in a
:: al
, Scons
(a
, d
), succ k
103 | None
-> [], s
.data
, 0
107 let (al
, d
, len
) = nget n s
in set_count s
(s
.count
- len
); set_data s d
; al
113 | None
-> raise Failure
118 Some _
-> raise Failure
125 Some a
-> junk strm
; ignore
(f a
); do_rec ()
131 (* Stream building functions *)
133 let from f
= {count
= 0; data
= Sgen
{curr
= None
; func
= f
}};;
136 {count
= 0; data
= List.fold_right
(fun x l
-> Scons
(x, l
)) l Sempty
}
140 from (fun c
-> if c
< String.length s
then Some s
.[c
] else None
)
145 data
= Sbuffio
{ic
= ic
; buff
= String.create
4096; len
= 0; ind
= 0}}
148 (* Stream expressions builders *)
150 let iapp i s
= {count
= 0; data
= Sapp
(i
.data
, s
.data
)};;
151 let icons i s
= {count
= 0; data
= Scons
(i
, s
.data
)};;
152 let ising i
= {count
= 0; data
= Scons
(i
, Sempty
)};;
155 {count
= 0; data
= Slazy
(fun _
-> Sapp
((f
()).data
, s
.data
))}
157 let lcons f s
= {count
= 0; data
= Slazy
(fun _
-> Scons
(f
(), s
.data
))};;
158 let lsing f
= {count
= 0; data
= Slazy
(fun _
-> Scons
(f
(), Sempty
))};;
160 let sempty = {count
= 0; data
= Sempty
};;
161 let slazy f
= {count
= 0; data
= Slazy
(fun _
-> (f
()).data
)};;
163 (* For debugging use *)
166 print_string
"{count = ";
168 print_string
"; data = ";
174 Sempty
-> print_string
"Sempty"
176 print_string
"Scons (";
182 print_string
"Sapp (";
187 | Slazy f
-> print_string
"Slazy"
188 | Sgen _
-> print_string
"Sgen"
189 | Sbuffio b
-> print_string
"Sbuffio"