module Netchannels:Object-oriented I/O: Basic types and classessig
..end
Contents
Netchannels_tut
.rec_in_channel
and rec_out_channel
: Primitive, but standardized levelraw_in_channel
and raw_out_channel
: Unix levelin_obj_channel
and out_obj_channel
: Application levelThe "raw" level represents the level of Unix file descriptors.
The application level is what should be used in programs. In addition
to the "raw" level one can find a number of convenience methods,
e.g. input_line
to read a line from the channel. The downside is that
these methods usually work only for blocking I/O.
One can lower the level by coercion, e.g. to turn an in_obj_channel
into a rec_in_channel
, apply the function
(fun ch -> (ch : in_obj_channel :> rec_in_channel))
To higher the level, apply lift_in
or lift_out
, defined below.
Interface changes: Since ocamlnet-0.98, the semantics of
the methods input
and output
has slightly changed. When the end
of the channel is reached, input
raises now End_of_file
. In previous
releases of ocamlnet, the value 0 was returned. When the channel cannot
process data, but is in non-blocking mode, both methods now return the
value 0. In previous releases of ocamlnet, the behaviour was not
defined.
Ocamlnet-3.0 changed the behavior of close_out
. Errors are no longer
reported - instead, the exception is logged to Netlog
. For a stricter
error handling, it is suggested to call flush
first. Also, close_in
and close_out
no longer raise Closed_channel
when the channel is
already closed.
exception Closed_channel
exception Buffer_underrun
exception Command_failure of Unix.process_status
close_in
or close_out
if the channel is connected with
another process, and the execution of that process fails.class type rec_in_channel =object
..end
class type raw_in_channel =object
..end
class type rec_out_channel =object
..end
class type raw_out_channel =object
..end
class type raw_io_channel =object
..end
class type compl_in_channel =object
..end
class type in_obj_channel =object
..end
class type compl_out_channel =object
..end
class type out_obj_channel =object
..end
class type io_obj_channel =object
..end
class type trans_out_obj_channel =object
..end
class input_channel :Pervasives.in_channel ->
in_obj_channel
in_channel
, which must be open.
class input_command :string ->
in_obj_channel
/bin/sh
, and reads the data the command prints
to stdout.
class input_string :?pos:int -> ?len:int -> string ->
in_obj_channel
val create_input_netbuffer : Netbuffer.t -> in_obj_channel * (unit -> unit)
Conversely, the user of this class may add new data to the netbuffer at any time. When the shutdown function is called, the EOF condition is recorded, and no further data must be added.
If the netbuffer becomes empty, the input methods raise Buffer_underrun
when the EOF condition has not yet been set, and they raise
End_of_file
when the EOF condition has been recorded.
val lexbuf_of_in_obj_channel : in_obj_channel -> Lexing.lexbuf
This function does not work for non-blocking channels.
val string_of_in_obj_channel : in_obj_channel -> string
This function does not work for non-blocking channels.
val with_in_obj_channel : (#in_obj_channel as 'a) -> ('a -> 'b) -> 'b
with_in_obj_channel ch f
:
Computes f ch
and closes ch
. If an exception happens, the channel is
closed, too.class output_channel :?onclose:unit -> unit -> Pervasives.out_channel ->
out_obj_channel
out_channel
.
class output_command :?onclose:unit -> unit -> string ->
out_obj_channel
/bin/sh
, and data written to the channel is
piped to stdin of the command.
class output_buffer :?onclose:unit -> unit -> Buffer.t ->
out_obj_channel
class output_netbuffer :?onclose:unit -> unit -> Netbuffer.t ->
out_obj_channel
class output_null :?onclose:unit -> unit -> unit ->
out_obj_channel
val with_out_obj_channel : (#out_obj_channel as 'a) -> ('a -> 'b) -> 'b
with_out_obj_channel ch f
:
Computes f ch
and closes ch
. If an exception happens, the channel is
closed, too.m
of the delegation class is called,
the definition of m
is just to call the method with the same
name m
of the parameter object. This is very useful in order
to redefine methods individually.
For example, to redefine the method pos_in
of an in_obj_channel
,
use
class my_channel = object(self)
inherit in_obj_channel_delegation ...
method pos_in = ...
end
As a special feature, the following delegation classes can suppress
the delegation of close_in
or close_out
, whatever applies.
Just pass close:false
to get this effect, e.g.
class input_channel_don't_close c =
in_obj_channel_delegation ~close:false (new input_channel c)
This class does not close c : in_channel
when the close_in
method is called.class rec_in_channel_delegation :?close:bool -> rec_in_channel ->
rec_in_channel
class raw_in_channel_delegation :?close:bool -> raw_in_channel ->
raw_in_channel
class in_obj_channel_delegation :?close:bool -> in_obj_channel ->
in_obj_channel
class rec_out_channel_delegation :?close:bool -> rec_out_channel ->
rec_out_channel
class raw_out_channel_delegation :?close:bool -> raw_out_channel ->
raw_out_channel
class out_obj_channel_delegation :?close:bool -> out_obj_channel ->
out_obj_channel
lift_in
and lift_out
functions work best.val lift_in : ?eol:string list ->
?buffered:bool ->
?buffer_size:int ->
[ `Raw of raw_in_channel | `Rec of rec_in_channel ] ->
in_obj_channel
rec_in_channel
or raw_in_channel
, depending on the passed
variant, into a full in_obj_channel
object. (This is a convenience
function, you can also use the classes below directly.) If you
want to define a class for the lifted object, use
class lifted_ch ... =
in_obj_channel_delegation (lift_in ...)
eol
: The accepted end-of-line delimiters. The method
input_line
recognizes any of the passed strings as EOL
delimiters. When more than one delimiter matches, the longest
is taken. Defaults to ["\n"]
. The default cannot be
changed when buffered=false
(would raise Invalid_argument
).
The delimiter strings must neither be empty, nor longer than
buffer_size
.buffered
: Whether a buffer is added, by default truebuffer_size
: The size of the buffer, if any, by default 4096val lift_out : ?buffered:bool ->
?buffer_size:int ->
[ `Raw of raw_out_channel | `Rec of rec_out_channel ] ->
out_obj_channel
rec_out_channel
or raw_out_channel
, depending on the passed
variant, into a full out_obj_channel
object. (This is a convenience
function, you can also use the classes below directly.) If you
want to define a class for the lifted object, use
class lifted_ch ... =
out_obj_channel_delegation (lift_out ...)
buffered
: Whether a buffer is added, by default truebuffer_size
: The size of the buffer, if any, by default 4096class virtual augment_raw_in_channel :object
..end
compl_in_channel
by calling
the methods of raw_in_channel
.
class lift_rec_in_channel :?start_pos_in:int -> rec_in_channel ->
in_obj_channel
pos_in
and the methods from compl_in_channel
by calling the methods of rec_in_channel
.
class virtual augment_raw_out_channel :object
..end
compl_out_channel
by calling
the methods of raw_out_channel
.
class lift_raw_out_channel :raw_out_channel ->
out_obj_channel
compl_out_channel
by calling
the methods of raw_out_channel
.
class lift_rec_out_channel :?start_pos_out:int -> rec_out_channel ->
out_obj_channel
pos_out
and the methods from compl_out_channel
by calling the methods of rec_out_channel
.
typeinput_result =
[ `Data of int | `Separator of string ]
enhanced_input
of enhanced_raw_in_channel
.`Data n
means that n
bytes have been copied to the target string`Separator s
means that no bytes have been copied, but that an
end-of-line separator s
has been foundclass type enhanced_raw_in_channel =object
..end
class buffered_raw_in_channel :?eol:string list -> ?buffer_size:int -> raw_in_channel ->
enhanced_raw_in_channel
raw_in_channel
.
class buffered_raw_out_channel :?buffer_size:int -> raw_out_channel ->
raw_out_channel
raw_out_channel
.
class input_descr :?blocking:bool -> ?start_pos_in:int -> Unix.file_descr ->
raw_in_channel
raw_in_channel
for the passed file descriptor, which must
be open for reading.
class output_descr :?blocking:bool -> ?start_pos_out:int -> Unix.file_descr ->
raw_out_channel
raw_out_channel
for the passed file descriptor, which must
be open for writing.
class socket_descr :?blocking:bool -> ?start_pos_in:int -> ?start_pos_out:int -> Unix.file_descr ->
raw_io_channel
raw_io_channel
for the passed socket descriptor, which must
be open for reading and writing, and not yet shut down in either
direction.
typeclose_mode =
[ `Commit | `Rollback ]
close_out
implies a commit or rollback operationclass buffered_trans_channel :?close_mode:close_mode -> out_obj_channel ->
trans_out_obj_channel
val make_temporary_file : ?mode:int ->
?limit:int ->
?tmp_directory:string ->
?tmp_prefix:string ->
unit -> string * Pervasives.in_channel * Pervasives.out_channel
tmp_directory
with a name
prefix tmp_prefix
and a unique suffix. The function returns
the triple (name, inch, outch) containing the file name
,
the file opened as in_channel inch
and as out_channel outch
.
mode
: The creation mask of the file; defaults to 0o600, i.e. the
file is private for the current userlimit
: Limits the number of trials to find the unique suffix.
Defaults to 1000.tmp_directory
: By default the current directorytmp_prefix
: By default "netstring"
. It is better to have a prefix
that is likely to be unique, e.g. the process ID, or the current time.class tempfile_trans_channel :?close_mode:close_mode -> ?tmp_directory:string -> ?tmp_prefix:string -> out_obj_channel ->
trans_out_obj_channel
class pipe :?conv:Netbuffer.t -> bool -> Netbuffer.t -> unit -> ?buffer_size:int -> unit ->
io_obj_channel
pipe
has two internal buffers (realized by Netbuffer).
class output_filter :io_obj_channel -> out_obj_channel ->
out_obj_channel
output_filter
filters the data written to it through the
io_obj_channel
(usually a pipe
), and writes the filtered data
to the passed out_obj_channel
.
class input_filter :in_obj_channel -> io_obj_channel ->
in_obj_channel
input_filter
filters the data read from it through the
io_obj_channel
(usually a pipe
after the data have been
retrieved from the passed in_obj_channel
.
output_filter
over input_filter
.
The latter is slower.
The primary application of filters is to encode or decode a channel on the fly. For example, the following lines write a BASE64-encoded file:
let ch = new output_channel (open_out "file.b64") in
let encoder = new Netencoding.Base64.encoding_pipe ~linelength:76 () in
let ch' = new output_filter encoder ch in
... (* write to ch' *)
ch' # close_out();
ch # close_out(); (* you must close both channels! *)
All bytes written to ch'
are BASE64-encoded and the encoded bytes are
written to ch
.
There are also pipes to decode BASE64, and to encode and decode the
"Quoted printable" format. Encoding and decoding work even if the
data is delivered in disadvantageous chunks, because the data is
"re-chunked" if needed. For example, BASE64 would require that data
arrive in multiples of three bytes, and to cope with that, the BASE64 pipe
only processes the prefix of the input buffer that is a multiple of three,
and defers the encoding of the extra bytes till the next opportunity.