File: bi_inbuf.ml

package info (click to toggle)
biniou 1.0.12-2
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 216 kB
  • sloc: ml: 1,808; makefile: 175
file content (106 lines) | stat: -rw-r--r-- 2,386 bytes parent folder | download | duplicates (2)
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
type t = {
  mutable i_s : string;
  mutable i_pos : int;
  mutable i_len : int;
  mutable i_offs : int;
  mutable i_max_len : int;
  i_refill : (t -> int -> unit);
  i_shared : Bi_share.Rd.tbl;
}

exception End_of_input

let try_preread ib n =
  if ib.i_len - ib.i_pos < n then (
    ib.i_refill ib n;
    min (ib.i_len - ib.i_pos) n
  )
  else
    n

let read ib n =
  let pos = ib.i_pos in
  if ib.i_len - pos >= n then (
    ib.i_pos <- pos + n;
    pos
  )
  else
    if try_preread ib n >= n then
      let pos = ib.i_pos in
      ib.i_pos <- ib.i_pos + n;
      pos
    else
      raise End_of_input

let read_char ib =
  let pos = ib.i_pos in
  if ib.i_len - pos > 0 then (
    let c = String.unsafe_get ib.i_s pos in
    ib.i_pos <- pos + 1;
    c
  )
  else
    if try_preread ib 1 > 0 then
      let pos = ib.i_pos in
      let c = String.unsafe_get ib.i_s pos in
      ib.i_pos <- pos + 1;
      c
    else
      raise End_of_input

let peek ib =
  let pos = ib.i_pos in
  if ib.i_len - pos > 0 then (
    String.unsafe_get ib.i_s pos
  )
  else
    if try_preread ib 1 > 0 then
      String.unsafe_get ib.i_s ib.i_pos
    else
      raise End_of_input

let from_string ?(pos = 0) ?(shrlen = 16) s = {
  i_s = s;
  i_pos = pos;
  i_len = String.length s;
  i_offs = -pos;
  i_max_len = String.length s;
  i_refill = (fun ib n -> ());
  i_shared = Bi_share.Rd.create shrlen;
}

(*
  Like Pervasives.really_input but returns the number of bytes
  read instead of raising End_of_file when the end of file is reached.
*)
let rec not_really_input ic s pos len accu =
  let n = input ic s pos len in
  if n < len && n > 0 then
    not_really_input ic s (pos + n) (len - n) (accu + n)
  else
    accu + n

let refill_from_channel ic ib n =
  if n > ib.i_max_len then
    invalid_arg "Bi_inbuf.refill_from_channel"
  else (
    let rem_len = ib.i_len - ib.i_pos in
    if rem_len < n then
      let s = ib.i_s in
      String.blit s ib.i_pos s 0 rem_len;
      let to_read = n - rem_len in
      let really_read = not_really_input ic s rem_len to_read 0 in
      ib.i_offs <- ib.i_offs + ib.i_pos;
      ib.i_pos <- 0;
      ib.i_len <- rem_len + really_read
  )

let from_channel ?(len = 4096) ?(shrlen = 16) ic = {
  i_s = String.create len;
  i_pos = 0;
  i_len = 0;
  i_offs = 0;
  i_max_len = len;
  i_refill = refill_from_channel ic;
  i_shared = Bi_share.Rd.create shrlen;
}