package gapi-ocaml

  1. Overview
  2. Docs
Legend:
Library
Module
Module type
Parameter
Class
Class type

Object-oriented I/O: Basic types and classes * * Contents * * - types * - input * - output * - delegation * - lifting * - descriptors * - transactional * - filters *

* * The tutorial has been moved to Netchannels_tut.

Types

There are three levels of class types for channels: * - rec_in_channel and rec_out_channel: Primitive, but standardized level * - raw_in_channel and raw_out_channel: Unix level * - in_obj_channel and out_obj_channel: Application level * * The "rec" level has been recently introduced to improve interoperability * with other libraries (e.g. camomile). The idea is to standardize the * real core methods of I/O, so they have the same meaning in all libraries. * Read * "Basic I/O class types" * for more. * * The "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. Read more about this in the section * Netchannels.rec_out_channel.close_error.

exception Closed_channel

Raised when channel operations are called when the channel is closed

exception Buffer_underrun

Raised by input methods if the internal buffer of the channel is too * empty to read even one byte of data. * This exception is only used by certain implementations of channel * classes.

exception Command_failure of Unix.process_status

Raised by 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

Recommended input class type for library interoperability.

class type raw_in_channel = object ... end

Basic Unix-level class type for input channels as used by ocamlnet. In addition * to the recommended standard, ocamlnet always support a position counter

class type rec_out_channel = object ... end

Recommended output class type for library interoperability.

class type raw_out_channel = object ... end

Basic Unix-level class type for output channels as used by ocamlnet. In addition * to the recommended standard, ocamlnet always support a position counter

class type raw_io_channel = object ... end

A channel supporting both input and output. The input and output * aspects are strictly separated

class type compl_in_channel = object ... end

Further methods usually supported by ocamlnet channel implementations. * These methods are only reasonable when the channel is of blocking type, * i.e. waits for input when not enough data are available to perform an * operation. Implementations may choose to fail when they detect the * channel is non-blocking.

class type in_obj_channel = object ... end

The application-level input channel supports raw and complemented methods

class type compl_out_channel = object ... end

Further methods usually supported by ocamlnet channel implementations. * These methods are only reasonable when the channel is of blocking type, * i.e. waits for output readiness when the underlying resource currently * cannot process enough data. Implementations may choose to fail when they * detect the channel is non-blocking.

class type out_obj_channel = object ... end

The application-level output channel supports raw and complemented methods

class type io_obj_channel = object ... end

A channel supporting both input and output. The input and output * aspects are strictly separated

class type trans_out_obj_channel = object ... end

A transactional output channel has a buffer for uncommitted data. * This means that all data written to this channel is collected in the * buffer until either commit_work or rollback_work is called. * * When the channel is closed, the buffer may optionally be committed. * This is implementation-defined. * * The method flush does not have any effect on the transaction * buffer.

Input channels

class input_channel : ?onclose:(unit -> unit) -> in_channel -> in_obj_channel

Creates an input channel from an in_channel, which must be open. * * The method pos_in reflects the real position in the channel as * returned by Pervasives.pos_in. This works for both seekable and * non-seekable channels. * * The method close_in also closes the underlying in_channel. * * The function onclose is called after the in_channel has been closed.

val input_channel : ?onclose:(unit -> unit) -> in_channel -> in_obj_channel

Same as function

class input_command : string -> in_obj_channel

Runs the command with /bin/sh, and reads the data the command prints * to stdout. * * The method pos_in returns the number of read octets. * * When close_in is invoked, the subprocess is waited for. If the * process exits with code 0, the method returns normally. Otherwise, * the exception Command_failure is raised.

val input_command : string -> in_obj_channel

Same as function

class input_string : ?pos:int -> ?len:int -> string -> in_obj_channel

Creates an input channel from a (constant) string. * * The method pos_in reflects the real position in the string, i.e. * a character read at position k can be found at s.[k] in the string * s. * *

val input_string : ?pos:int -> ?len:int -> string -> in_obj_channel

Same as function

class input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel

Same for constant bytes

val input_bytes : ?pos:int -> ?len:int -> Bytes.t -> in_obj_channel

Same as function

class input_memory : ?pos:int -> ?len:int -> Netsys_types.memory -> in_obj_channel

Same for constant memory

val input_memory : ?pos:int -> ?len:int -> Netsys_types.memory -> in_obj_channel

Same as function

val input_tstring : ?pos:int -> ?len:int -> Netsys_types.tstring -> in_obj_channel

Same for tagged strings (only as function)

val create_input_netbuffer : ?keep_data:bool -> Netbuffer.t -> in_obj_channel * (unit -> unit)

Creates an input channel and a shutdown function for a netbuffer. * This is a destructive * implementation: Every time data is read, the octets are taken from the * beginning of the netbuffer, and they are deleted from the netbuffer * (recall that a netbuffer works like a queue of characters). * * 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. * * keep_data: do not delete read data from the buffer

val lexbuf_of_in_obj_channel : in_obj_channel -> Lexing.lexbuf

Creates a lexical buffer from an input channel. The input channel * is not closed when the end is reached * * This function does not work for non-blocking channels.

val string_of_in_obj_channel : in_obj_channel -> string

Reads from the input channel until EOF and returns the characters * as string. The input channel is not closed. * * This function does not work for non-blocking channels.

val bytes_of_in_obj_channel : in_obj_channel -> Bytes.t

Same for bytes

val lines_of_in_obj_channel : in_obj_channel -> string list

Reads from the input channel until EOF and returns the lines * as string list. The input channel is not closed. * * 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.

Output channels

class output_channel : ?onclose:(unit -> unit) -> out_channel -> out_obj_channel

Creates an output channel writing into an out_channel. * * The method pos_out reflects the real position in the channel as * returned by Pervasives.pos_out. This works for both seekable and * non-seekable channels. * * The method close_out also closes the underlying out_channel. * There is some implicit logic to either use close_out or close_out_noerr * depending on whether the immediately preceding operation already reported * an error. * *

class output_command : ?onclose:(unit -> unit) -> string -> out_obj_channel

Runs the command with /bin/sh, and data written to the channel is * piped to stdin of the command. * * The method pos_out returns the number of written octets. * * When close_out is invoked, the subprocess is waited for. If the * process exits with code 0, the method returns normally. Otherwise, * the exception Command_failure is raised. (The channel is closed * even if this exception is raised.) * *

class output_buffer : ?onclose:(unit -> unit) -> Buffer.t -> out_obj_channel

This output channel writes the data into the passed buffer. * * The method pos_out returns the number of written octets. * *

class output_netbuffer : ?onclose:(unit -> unit) -> Netbuffer.t -> out_obj_channel

This output channel writes the data into the passed netbuffer. * * The method pos_out returns the number of written octets. * *

class output_null : ?onclose:(unit -> unit) -> unit -> out_obj_channel

This output channel discards all written data. * * The method pos_out returns the number of discarded bytes. * *

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.

Delegation classes

Delegation classes just forward method calls to an parameter * object, i.e. when method 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.

Description * * This class type is defined in * "Basic I/O class types" * as collaborative effort of several library creators.

Description * * This class type is defined in * "Basic I/O class types" * as collaborative effort of several library creators.

Lifting channels

The following classes and functions add missing methods to reach * a higher level in the hierarchy of channel class types. For most * uses, the lift_in and lift_out functions work best.

val lift_in : ?eol:string list -> ?buffered:bool -> ?buffer_size:int -> ?pass_through:int -> [ `Rec of rec_in_channel | `Raw of raw_in_channel ] -> in_obj_channel

Turns a 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 ...)
* 

* *

  • parameter 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. *

    @param buffered

    Whether a buffer is added, by default true *

    @param buffer_size

    The size of the buffer, if any, by default 4096 *

    @param pass_through

    If the read request has at least this size, * and the buffer is currently empty, the buffer will be bypassed. * Defaults to max_int, i.e. it is off.

val lift_out : ?buffered:bool -> ?buffer_size:int -> ?pass_through:int -> [ `Rec of rec_out_channel | `Raw of raw_out_channel ] -> out_obj_channel

Turns a 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 ...)
* 

* *

  • parameter buffered

    Whether a buffer is added, by default true *

    @param buffer_size

    The size of the buffer, if any, by default 4096 *

    @param pass_through

    If the write request has at least this size, * and the buffer is currently empty, the buffer will be bypassed. * Defaults to max_int, i.e. it is off.

class virtual augment_raw_in_channel : object ... end

This class implements the methods from compl_in_channel by calling * the methods of raw_in_channel. There is no additional buffering. * The performance of the method input_line is very bad (consider * to override it, e.g. by enhanced_input_line as defined below).

class lift_rec_in_channel : ?start_pos_in:int -> rec_in_channel -> in_obj_channel

This class implements pos_in and the methods from compl_in_channel * by calling the methods of rec_in_channel. * There is no additional buffering. * * The performance of the method input_line is very bad (consider * to override it, e.g. by enhanced_input_line as defined below). * * The method pos_in is implemented by counting the number of octets * read by the input method. * *

class virtual augment_raw_out_channel : object ... end

This class implements the methods from compl_out_channel by calling * the methods of raw_out_channel. There is no additional buffering.

This class implements the methods from compl_out_channel by calling * the methods of raw_out_channel. There is no additional buffering.

class lift_rec_out_channel : ?start_pos_out:int -> rec_out_channel -> out_obj_channel

This class implements pos_out and the methods from compl_out_channel * by calling the methods of rec_out_channel. * There is no additional buffering. * * The method pos_out is implemented by counting the number of octets * read by the output method. * *

type input_result = [
  1. | `Data of int
  2. | `Separator of string
]

This type is for the method 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 found

class type enhanced_raw_in_channel = object ... end

Defines private methods reading text line by line

class buffered_raw_in_channel : ?eol:string list -> ?buffer_size:int -> ?pass_through:int -> raw_in_channel -> enhanced_raw_in_channel

This class adds a buffer to the underlying raw_in_channel. * As additional feature, the method enhanced_input_line is a fast * version of input_line that profits from the buffer. * *

class buffered_raw_out_channel : ?buffer_size:int -> ?pass_through:int -> raw_out_channel -> raw_out_channel

This class adds a buffer to the underlying raw_out_channel. * *

Channels over descriptors

class input_descr : ?blocking:bool -> ?start_pos_in:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_in_channel

Creates a raw_in_channel for the passed file descriptor, which must * be open for reading. * * The pos_in method returns logical positions, i.e. it counts the number * of read octets. It is not tried to determine the real file position. * * The method close_in also closes the file descriptor. * * This class also supports Win32 proxy descriptors referring to an input * channel. * *

class output_descr : ?blocking:bool -> ?start_pos_out:int -> ?fd_style:Netsys.fd_style -> Unix.file_descr -> raw_out_channel

Creates a raw_out_channel for the passed file descriptor, which must * be open for writing. * * The pos_out method returns logical positions, i.e. it counts the number * of written octets. It is not tried to determine the real file position. * * The method close_out also closes the file descriptor. * * This class also supports Win32 proxy descriptors referring to an output * channel. * *

class socket_descr : ?blocking:bool -> ?start_pos_in:int -> ?start_pos_out:int -> ?fd_style: Netsys.fd_style -> Unix.file_descr -> raw_io_channel

Creates a raw_io_channel for the passed socket descriptor, which must * be open for reading and writing, and not yet shut down in either * direction. The raw_io_channel is used to represent a bidirectional * channel: close_out shuts the socket down for sending, close_in * shuts the socket down for reading, and when both directions are down, * the descriptor is closed. * * The pos_in and pos_out methods returns logical positions. * * This class supports sockets and Win32 named pipes. Note, however, * that for Win32 named pipes it is not possible to shut down only one * direction of the bidirectional data channel. * *

Transactional channels

type close_mode = [
  1. | `Commit
  2. | `Rollback
]

Whether a close_out implies a commit or rollback operation

A transactional output channel with a transaction buffer implemented * in memory * *

val make_temporary_file : ?mode:int -> ?limit:int -> ?tmp_directory:string -> ?tmp_prefix:string -> unit -> string * in_channel * out_channel

Creates a temporary file in the directory 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. * *

  • parameter tmp_directory

    Defaults to Netsys_tmp.tmp_directory() *

    @param tmp_prefix

    By default "netstring". This needs not to be * unique, but just descriptive. *

    @param mode

    The creation mask of the file; defaults to 0o600, i.e. the * file is private for the current user *

    @param limit

    Limits the number of trials to find the unique suffix. * Defaults to 1000.

class tempfile_trans_channel : ?close_mode:close_mode -> ?tmp_directory:string -> ?tmp_prefix:string -> out_obj_channel -> trans_out_obj_channel

A transactional output channel with a transaction buffer implemented * as temporary file * *

Pipes and Filters

Note that this has nothing to do with "pipes" on the Unix level. * It is, however, the same idea: Connecting two I/O resources with an * intermediate buffer.

class pipe : ?conv:(Netbuffer.t -> bool -> Netbuffer.t -> unit) -> ?buffer_size:int -> unit -> io_obj_channel

A pipe has two internal buffers (realized by Netbuffer). The * output methods of the class write to the incoming buffer. When * new data are appended to the incoming buffer, the conversion function * conv is called; the arguments are the incoming buffer and the outgoing * buffer. The conversion function must convert the data available in the * incoming buffer and append the result to the outgoing buffer. Finally, * the input methods of the class return the data found in the outgoing * buffer. * * The conversion function is called as follows: * conv incoming_buffer at_eof outgoing_buffer * * The conversion function is allowed to do nothing if the incoming data * are not complete enough to be converted. It is also allowed to convert * only the beginning of the incoming buffer. * * If the outgoing buffer is empty, the input methods will raise * Buffer_underrun. * * If close_out is invoked, the end of the data stream will be recorded. * In this case, the conversion function is called with at_eof = true, * and it is expected that this function converts the whole data found * in the incoming buffer. * * close_in implies close_out. * * The conversion function may raise exceptions. The exceptions will * fall through to the caller of the input methods. (The output methods * and close_in, close_out never fail because of such exceptions.) * * The default conversion function copies everything from the incoming * buffer to the outgoing buffer without modification.

An 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. * * If the filter is closed, the io_obj_channel will be closed, too, * but not the destination out_obj_channel (so you can still append * further data).

An 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. * * An input_filter object never generates Buffer_underrun exceptions. * However, if the passed in_obj_channel or io_obj_channel raises such * an exception, the exception will fall through the calling chain. * * If the filter is closed, the io_obj_channel will be closed, too, * but not the source in_obj_channel (so you can still read further * data from it).

Notes, Examples

If you have the choice, prefer 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.

OCaml

Innovation. Community. Security.