package iostream

  1. Overview
  2. Docs
Generic, composable IO input and output streams

Install

Dune Dependency

Authors

Maintainers

Sources

iostream-0.2.2.tbz
sha256=6d2725f20fcca4fe8c8c54fcaa442fb088f20d1c5788c437182042cfcce3829d
sha512=8eb87e13ff448d627062ffb2b0e9b10c29fe5406dcac24889499f358a9d1c50fc1ea02dc601f49fecebd38833b415431265e7fad991a55308923f63fb0aa79ad

doc/src/iostream/in_buf.ml.html

Source file in_buf.ml

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 =
  (* see if we can directly extract a line from current buffer *)
  let slice = fill_buf self in
  if slice.len = 0 then
    None
  else (
    match Slice.find_index_exn slice '\n' with
    | j ->
      (* easy case: buffer already contains a full line *)
      let line = Bytes.sub_string slice.bytes slice.off (j - slice.off) in
      consume self (j - slice.off + 1);
      Some line
    | exception Not_found ->
      (* Need to re-fill [self.buf]. We must first create a new holding buffer,
         already filled with beginning of line. *)
      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;

      (* now read until we find ['\n'] *)
      let continue = ref true in
      while !continue do
        let bs = fill_buf self in
        if bs.len = 0 then continue := false (* EOF *);
        match Slice.find_index_exn bs '\n' with
        | j ->
          Buffer.add_subbytes buf bs.bytes bs.off (j - bs.off);
          (* without '\n' *)
          consume self (j - bs.off + 1);
          (* consume, including '\n' *)
          continue := false
        | exception Not_found ->
          (* the whole [self.buf] is part of the current line. *)
          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
OCaml

Innovation. Community. Security.