2 * $Id: lm_io.ml 7878 2005-10-09 00:13:24Z jyh $
5 * Moved here from Pervasives
13 external fopen
: string -> int -> int -> int = "%file_open"
14 external fclose
: int -> unit = "%file_close"
15 external fread
: int -> string -> int -> int -> int = "%file_read"
16 external fwrite
: int -> string -> int -> int -> int = "%file_write"
17 external fseek
: int -> int -> unit = "%file_seek"
18 external ftell
: int -> int = "%file_tell"
19 external flength
: int -> int = "%file_len"
21 let code = int_of_char
25 * An in-channel contains a buffer.
28 { mutable chan_fd
: int;
30 mutable chan_min
: int;
31 mutable chan_max
: int
34 type in_channel
= channel
35 type out_channel
= channel
44 chan_buf
= screate
bufsize;
50 let stdout = mk_chan 1
51 let stderr = mk_chan 2
54 * Convert the open flags.
79 let rec mask_of_flags mask
= function
83 Open_rdonly
-> o_rdonly
84 | Open_wronly
-> o_wronly
85 | Open_append
-> o_append
86 | Open_creat
-> o_creat
87 | Open_trunc
-> o_trunc
89 | Open_binary
-> o_binary
91 | Open_nonblock
-> o_nonblock
93 mask_of_flags (mask lor mask'
) t
98 * Opening and closing.
100 let open_gen mask flags umask name
=
101 let mask = mask_of_flags 0 flags
in
102 let fd = fopen name
mask umask
in
104 raise
(Sys_error name
);
107 let open_out_gen = open_gen o_wronly
108 let open_in_gen = open_gen o_rdonly
110 let open_out_bin = open_gen (o_wronly lor o_binary) [] 438
111 let open_out = open_gen o_wronly [] 438
113 let open_in_bin = open_gen (o_rdonly lor o_binary) [] 0
114 let open_in = open_gen o_rdonly [] 0
117 let fd = chan
.chan_fd
in
123 let close_out = close
126 * Filling and flushing.
129 let { chan_fd
= fd; chan_buf
= buf
} = chan
in
130 let count = fread
fd buf
0 bufsize in
134 chan
.chan_max
<- count
137 let { chan_fd
= fd; chan_buf
= buf
; chan_min
= min
; chan_max
= max
} = chan
in
138 let rec writebuf min
=
140 let count = max
- min
in
141 let count = fwrite
fd buf min
count in
144 chan
.chan_min
<- min
;
147 writebuf (min
+ count)
156 let output_char chan c
=
157 if chan
.chan_max
= bufsize then
159 let max = chan
.chan_min
in
160 chan
.chan_buf
.[max] <- c
;
161 chan
.chan_max
<- succ
max
163 let rec writebuf fd buf off len
=
165 let count = len
- off
in
166 let count = fwrite
fd buf off
count in
169 writebuf fd buf
(off
+ count) len
171 let output chan buf off len
=
172 if len
- off
>= bufsize then
175 writebuf chan
.chan_fd buf off len
;
181 if chan
.chan_max
+ len
- off
> bufsize then
183 sblit buf off chan
.chan_buf chan
.chan_max len
;
184 chan
.chan_max
<- chan
.chan_max
+ len
187 let output_string chan s
=
188 output chan s
0 (slength s
)
190 let output_byte chan i
=
191 output_char chan
(chr i
)
193 let output_binary_int chan i
=
194 output_byte chan
((i
lsr 24) land 255);
195 output_byte chan
((i
lsr 16) land 255);
196 output_byte chan
((i
lsr 8) land 255);
197 output_byte chan
(i
land 255)
199 let seek_out chan loc
=
201 fseek chan
.chan_fd loc
207 let out_channel_length chan
=
211 let set_binary_mode_out chan flag
=
218 let min = chan
.chan_min
in
220 raise
(Invalid_argument
"ungetc");
221 chan
.chan_min
<- pred
min
223 let set_binary_mode_in chan flag
=
226 let rec input_char chan
=
227 let { chan_buf
= buf
; chan_min
= min; chan_max
= max } = chan
in
235 chan
.chan_min
<- succ
min;
239 let input_byte chan
=
240 code (input_char chan
)
242 let input_binary_int chan
=
243 let c1 = input_byte chan
in
244 let c2 = input_byte chan
in
245 let c3 = input_byte chan
in
246 let c4 = input_byte chan
in
247 ((c1 lsl 24) lor (c2 lsl 16) lor (c3 lsl 8) lor c4)
249 let rec input_line chan
=
250 let { chan_buf
= buf
; chan_min
= min; chan_max
= max } = chan
in
257 let rec search s i
min max =
259 let s = s ^
(ssub buf
min max) in
262 search s chan
.chan_min chan
.chan_min chan
.chan_max
266 else if buf
.[i
] = '
\n'
then
267 let s = s ^
(ssub buf
min i
) in
268 chan
.chan_min
<- succ i
;
271 search s (succ i
) min max
273 search "" chan
.chan_min chan
.chan_min chan
.chan_max
275 let input chan buf off len
=
276 if chan
.chan_min
= chan
.chan_max
then
278 let { chan_buf
= buf'
; chan_min
= min'
; chan_max
= max'
} = chan
in
279 let count = max'
- min'
in
282 sblit buf'
min' buf off
count;
289 sblit buf'
min' buf off len
;
290 chan
.chan_min
<- min'
+ len
;
294 let really_input chan buf off len
=
295 let rec read amount off len
=
297 let { chan_buf
= buf'
; chan_min
= min'
; chan_max
= max'
} = chan
in
298 let count = max'
- min'
in
300 let amount = amount + count in
301 let _ = sblit buf'
min' buf off
count in
302 let off = off + count in
303 let len = len - count in
307 let amount = amount + len in
308 sblit buf'
min' buf
off len;
309 chan
.chan_min
<- chan
.chan_min
+ len
316 let seek_in chan pos
=
319 fseek chan
.chan_fd pos
322 let pos = ftell chan
.chan_fd
in
323 pos - (chan
.chan_max
- chan
.chan_min
)
325 let in_channel_length chan
=
329 * Standard operations.
331 let print_char = output_char stdout
333 let print_string = output_string stdout
336 print_string (string_of_int i
)
339 print_string (string_of_float x
)
341 let print_newline () =
344 let print_endline s =
348 let prerr_char = output_char stderr
350 let prerr_string = output_string stderr
353 prerr_string (string_of_int i
)
356 prerr_string (string_of_float x
)
358 let prerr_newline () =
361 let prerr_endline s =
368 let is_digit = function
383 let int_of_digit = function
395 raise
(Invalid_argument
"int_of_digit")
397 let is_space = function
410 let rec skip_white chan
=
411 let c = input_char chan
in
422 let c = input_char chan
in
433 let c = input_char chan
in
435 input (i
* 10 + int_of_digit c)
448 * Read a floating point number.
454 | FloatSignedExponent
458 let input_float chan
=
459 let buf = screate
fbufsize in
460 let _ = skip_white chan
in
461 let c = input_char chan
in
471 let rec loop state i
=
475 let c = input_char chan
in
480 loop FloatInt
(succ i
)
481 else if c == '
.'
then
482 loop FloatDecimal
(succ i
)
483 else if c == 'e'
|| c == 'E'
then
484 loop FloatExponent
(succ i
)
491 loop FloatDecimal
(succ i
)
492 else if c == 'e'
|| c == 'E'
then
493 loop FloatExponent
(succ i
)
498 if c == '
-'
|| c == '
+'
then
499 loop FloatSignedExponent
(succ i
)
500 else if is_digit c then
501 loop FloatSignedExponent
(succ i
)
505 | FloatSignedExponent
->
507 loop FloatSignedExponent
(succ i
)
511 let i = loop FloatInt
0 in
512 float_of_string
(ssub
buf 0 i)