1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
open Slice
open Common_
class type t =
object
inherit In.t
method fill_buf : unit -> Slice.t
method consume : int -> unit
end
class virtual t_from_refill ?(bytes = Bytes.create _default_buf_size) () =
let slice = Slice.of_bytes bytes in
object (self)
method virtual private refill : Slice.t -> unit
method fill_buf () : Slice.t =
if slice.len = 0 then self#refill slice;
slice
method consume (n : int) : unit = Slice.consume slice n
(** Consume [n] bytes from the inner buffer. *)
method input b i len : int =
let buf = self#fill_buf () in
if buf.len > 0 then (
let n = min len buf.len in
Bytes.blit buf.bytes buf.off b i n;
Slice.consume buf n;
n
) else
0
(** Default implementation of [input] using [fill_buf] *)
end
let[@inline] consume (self : #t) n = self#consume n
let[@inline] fill_buf (self : #t) : Slice.t = self#fill_buf ()
let create ?(bytes = Bytes.create _default_buf_size) ?(close = ignore) ~refill
() : t =
object
inherit t_from_refill ~bytes ()
method close () = close ()
method private refill buf : unit =
buf.off <- 0;
buf.len <- refill buf.bytes
end
let[@inline] input self b i len : int = self#input b i len
let[@inline] close self = self#close ()
class bufferized ?(bytes = Bytes.create _default_buf_size) (ic : #In.t) : t =
let eof = ref false in
object
inherit t_from_refill ~bytes ()
method close () = ic#close ()
method private refill buf =
if not !eof then (
buf.off <- 0;
buf.len <- ic#input buf.bytes 0 (Bytes.length buf.bytes);
if buf.len = 0 then eof := true
)
end
let[@inline] bufferized ?bytes ic = new bufferized ?bytes ic
class of_bytes ?(off = 0) ?len bytes : t =
let len =
match len with
| None -> Bytes.length bytes - off
| Some n ->
if n > Bytes.length bytes - off then
invalid_arg "In_buf.of_bytes: invalid length";
n
in
let slice = { bytes; off; len } in
object
method close () = ()
method fill_buf () = slice
method input b i len : int =
if slice.len > 0 then (
let n = min len slice.len in
Bytes.blit slice.bytes slice.off b i n;
Slice.consume slice n;
n
) else
0
method consume n = Slice.consume slice n
end
let[@inline] of_bytes ?off ?len bs = new of_bytes ?off ?len bs
class of_string ?off ?len s =
object
inherit of_bytes ?off ?len (Bytes.unsafe_of_string s)
end
let[@inline] of_string ?off ?len bs = new of_string ?off ?len bs
class of_in ?bytes ic =
object
inherit t_from_refill ?bytes ()
method close () = In.close ic
method private refill buf =
buf.off <- 0;
buf.len <- In.input ic buf.bytes 0 (Bytes.length buf.bytes)
end
let[@inline] of_in ?bytes ic = new of_in ?bytes ic
class of_in_channel ?bytes ic =
object
inherit of_in ?bytes (In.of_in_channel ic)
end
let[@inline] of_in_channel ?bytes ic : t = new of_in_channel ?bytes ic
class open_file ?bytes ?mode ?flags filename : t =
of_in ?bytes (In.open_file ?mode ?flags filename)
let[@inline] open_file ?bytes ?mode ?flags filename =
new open_file ?bytes ?mode ?flags filename
let with_open_file ?bytes ?mode ?flags filename f =
let ic = open_file ?bytes ?mode ?flags filename in
Fun.protect ~finally:ic#close (fun () -> f ic)
let[@inline] into_in (self : #t) : In.t = (self :> In.t)
let input_all_into_buffer = In.input_all_into_buffer
let input_all = In.input_all
let copy_into (self : #t) (oc : #Out.t) : unit =
let continue = ref true in
while !continue do
let buf = fill_buf self in
if buf.len = 0 then
continue := false
else (
Out.output oc buf.bytes 0 buf.len;
consume self buf.len
)
done
let input_line ?buffer (self : #t) : string option =
let slice = fill_buf self in
if slice.len = 0 then
None
else (
match Slice.find_index_exn slice '\n' with
| j ->
let line = Bytes.sub_string slice.bytes slice.off (j - slice.off) in
consume self (j - slice.off + 1);
Some line
| exception Not_found ->
let buf =
match buffer with
| Some b ->
Buffer.clear b;
b
| None -> Buffer.create 256
in
Buffer.add_subbytes buf slice.bytes slice.off slice.len;
consume self slice.len;
let continue = ref true in
while !continue do
let bs = fill_buf self in
if bs.len = 0 then continue := false ;
match Slice.find_index_exn bs '\n' with
| j ->
Buffer.add_subbytes buf bs.bytes bs.off (j - bs.off);
consume self (j - bs.off + 1);
continue := false
| exception Not_found ->
Buffer.add_subbytes buf bs.bytes bs.off bs.len;
consume self bs.len
done;
Some (Buffer.contents buf)
)
let input_lines ?(buffer = Buffer.create 32) ic =
let rec loop l =
match input_line ~buffer ic with
| None -> List.rev l
| Some s -> loop (s :: l)
in
loop []
let to_iter (self : #t) k : unit =
let continue = ref true in
while !continue do
let bs = fill_buf self in
if bs.len = 0 then
continue := false
else (
for i = 0 to bs.len - 1 do
k (Bytes.get bs.bytes i)
done;
consume self bs.len
)
done
let to_seq (self : #t) : char Seq.t =
let continue = ref true in
let rec next () =
if not !continue then
Seq.Nil
else (
let slice = fill_buf self in
if slice.len = 0 then (
continue := false;
Seq.Nil
) else (
let c = Bytes.get slice.bytes slice.off in
Slice.consume slice 1;
Seq.Cons (c, next)
)
)
in
next
let of_seq ?bytes seq : t =
let seq = ref seq in
object
inherit t_from_refill ?bytes ()
method close () = ()
method private refill bs =
let rec loop idx =
if idx >= Bytes.length bs.bytes then
idx
else (
match !seq () with
| Seq.Nil -> idx
| Seq.Cons (c, seq_tl) ->
seq := seq_tl;
Bytes.set bs.bytes idx c;
loop (idx + 1)
)
in
bs.off <- 0;
bs.len <- loop 0
end
let skip (self : #t) (n : int) : unit =
let n = ref n in
while !n > 0 do
let slice = fill_buf self in
let len = min !n slice.len in
Slice.consume slice len;
n := !n - len
done