forked from ocaml-community/biniou
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbi_inbuf.ml
106 lines (97 loc) · 2.33 KB
/
bi_inbuf.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
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;
}