
  * BatInnerIO - Abstract input / output ( inner module ) 
  * Copyright ( C ) 2003   
  *                2008   
  *                2008   
  * 
  * This library is free software ; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public 
  * License as published by the Free Software Foundation ; either 
  * version 2.1 of the License , or ( at your option ) any later version , 
  * with the special exception on linking described in file LICENSE . 
  * 
  * This library is distributed in the hope that it will be useful , 
  * but WITHOUT ANY WARRANTY ; without even the implied warranty of 
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .   See the GNU 
  * Lesser General Public License for more details . 
  * 
  * You should have received a copy of the GNU Lesser General Public 
  * License along with this library ; if not , write to the Free Software 
  * Foundation , Inc. , 59 Temple Place , Suite 330 , Boston , MA   02111 - 1307   USA 
 
 * BatInnerIO - Abstract input/output (inner module)
 * Copyright (C) 2003 Nicolas Cannasse
 *               2008 David Teller
 *               2008 Philippe Strauss
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version,
 * with the special exception on linking described in file LICENSE.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)


* 
    Core of the BatIO module . 

    This module contains the core definitions of { ! BatIO } , so as to avoid circular 
    dependencies between modules which only need simple functions of { ! BatIO } and 
    that module itself . 

    Do n't use this module , use { ! BatIO } . 

    @author   
    @author   
    @author   
    @author   

   Core of the BatIO module.

   This module contains the core definitions of {!BatIO}, so as to avoid circular
   dependencies between modules which only need simple functions of {!BatIO} and
   that module itself.

   Don't use this module, use {!BatIO}.

   @author Nicolas Cannasse
   @author David Teller
   @author Philippe Strauss
   @author Edgar Friendly
*)

type input
type 'a output

exception No_more_input
* This exception is raised when reading on an input with the [ read ] or 
     [ nread ] functions while there is no available token to read .
    [nread] functions while there is no available token to read. *)

exception Input_closed
(** This exception is raised when reading on a closed input. *)

exception Output_closed
(** This exception is raised when reading on a closed output. *)

val read : input -> char
(** Read a single char from an input or raise [No_more_input] if
    no input available. *)

val read_all : input -> string
(** read all the contents of the input until [No_more_input] is raised. *)

val pipe : unit -> input * unit output
(** Create a pipe between an input and an output. Data written from
    the output can be read from the input. *)

val nread : input -> int -> string
(** [nread i n] reads a string of size up to [n] from an input.
    The function will raise [No_more_input] if no input is available.
    It will raise [Invalid_argument] if [n] < 0. *)

val really_nread : input -> int -> string
(** [really_nread i n] reads a string of exactly [n] characters
    from the input. @raise No_more_input if at least [n] characters are
    not available. @raise Invalid_argument if [n] < 0. *)

val input : input -> Bytes.t -> int -> int -> int
* [ input i s   ] reads up to [ len ] bytes from the given input , 
     storing them in byte sequence [ s ] , starting at position [ p ] . It 
     returns the actual number of bytes read or raise 
     [ No_more_input ] if no character can be read . It will raise 
     [ Invalid_argument ] if [ p ] and [ len ] do not designate a valid 
     subsequence of [ s ] .
    storing them in byte sequence [s], starting at position [p]. It
    returns the actual number of bytes read or raise
    [No_more_input] if no character can be read. It will raise
    [Invalid_argument] if [p] and [len] do not designate a valid
    subsequence of [s]. *)

val really_input : input -> Bytes.t -> int -> int -> int
* [ really_input i s   ] reads exactly [ len ] characters from the 
     given input , storing them in the byte sequence [ s ] , starting at 
     position [ p ] . For consistency with { ! BatIO.input } it returns 
     [ len ] . @raise No_more_input if at least [ len ] characters are not 
     available . @raise Invalid_argument if [ p ] and [ len ] do not designate 
     a valid subsequence of [ s ] .
    given input, storing them in the byte sequence [s], starting at
    position [p]. For consistency with {!BatIO.input} it returns
    [len]. @raise No_more_input if at least [len] characters are not
    available. @raise Invalid_argument if [p] and [len] do not designate
    a valid subsequence of [s]. *)

val close_in : input -> unit
(** Close the input. It can no longer be read from. *)

(*val auto_close_in : input -> input
  (** Create a new channel which will close automatically once there is nothing
    left to read.*)*)

val write : 'a output -> char -> unit
(** Write a single char to an output. *)

val nwrite : 'a output -> string -> unit
(** Write a string to an output. *)

val nwrite_bytes : 'a output -> Bytes.t -> unit
* Write a byte sequence to an output . 

     @since 2.8.0

    @since 2.8.0 *)

val output : 'a output -> Bytes.t -> int -> int -> int
* [ output o s   ] writes up to [ len ] characters from byte 
     sequence [ len ] , starting at offset [ p ] . It returns the number of 
     characters written . It will raise [ Invalid_argument ] if [ p ] and 
     [ len ] do not designate a valid subsequence of [ s ] .
    sequence [len], starting at offset [p]. It returns the number of
    characters written. It will raise [Invalid_argument] if [p] and
    [len] do not designate a valid subsequence of [s]. *)

val output_substring : 'a output -> string -> int -> int -> int
* like [ output ] above , but outputs from a substring instead of 
     a subsequence of bytes 

     @since 2.8.0
    a subsequence of bytes

    @since 2.8.0 *)

val really_output : 'a output -> Bytes.t -> int -> int -> int
* [ really_output o s   ] writes exactly [ len ] characters from 
     byte sequence [ s ] onto the the output , starting with the character 
     at offset [ p ] . For consistency with { ! BatIO.output } it returns 
     [ len ] . @raise Invalid_argument if [ p ] and [ len ] do not designate 
     a valid subsequence of [ s ] .
    byte sequence [s] onto the the output, starting with the character
    at offset [p]. For consistency with {!BatIO.output} it returns
    [len]. @raise Invalid_argument if [p] and [len] do not designate
    a valid subsequence of [s]. *)

val really_output_substring : 'a output -> string -> int -> int -> int
* like [ really_output ] above , but outputs from a substring instead 
     of a subsequence of bytes 

     @since 2.8.0
    of a subsequence of bytes

    @since 2.8.0 *)

val flush : 'a output -> unit
(** Flush an output. *)

val flush_all : unit -> unit
(** Flush all outputs. *)

val close_out : 'a output -> 'a
(** Close the output and return its accumulator data.
    It can no longer be written. *)

val close_all : unit -> unit
(** Close all outputs.
    Ignore errors.*)

val input_string : string -> input
(** Create an input that will read from a string. *)

val output_string : unit -> string output
(** Create an output that will write into a string in an efficient way.
    When closed, the output returns all the data written into it. *)

val on_close_out : 'a output -> ('a output -> unit) -> unit
(**
   Register a function to be triggered just before an output is closed.
*)

val create_in :
  read:(unit -> char) ->
  input:(Bytes.t -> int -> int -> int) ->
  close:(unit -> unit) -> input
* Fully create an input by giving all the needed functions . 

     { b Note } Do { e not } use this function for creating an input 
     which reads from one or more underlying inputs . Rather , use 
     { ! wrap_in } . 


    {b Note} Do {e not} use this function for creating an input
    which reads from one or more underlying inputs. Rather, use
    {!wrap_in}.
*)

val inherit_in:
  ?read:(unit -> char) ->
  ?input:(Bytes.t -> int -> int -> int) ->
  ?close:(unit -> unit) ->
  input -> input
* 
    Simplified and optimized version of { ! wrap_in } whenever only 
    one input appears as dependency . 

   Simplified and optimized version of {!wrap_in} whenever only
   one input appears as dependency.
*)


val wrap_in :
  read:(unit -> char) ->
  input:(Bytes.t -> int -> int -> int) ->
  close:(unit -> unit) ->
  underlying:(input list) ->
  input
(** Fully create an input reading from other inputs by giving all the needed functions.

    This function is a more general version of {!create_in}
    which also handles dependency management between inputs.
*)




val create_out :
  write:(char -> unit) ->
  output:(Bytes.t -> int -> int -> int) ->
  flush:(unit -> unit) ->
  close:(unit -> 'a) ->
  'a output
* 
     Fully create an output by giving all the needed functions . 

     @param write   Write one character to the output ( see { ! write } ) . 
     @param output Write a ( sub)string to the output ( see { ! output } ) . 
     @param flush   Flush any buffers of this output   ( see { ! flush } ) . 
     @param close   Close this output . The output will be automatically 
     flushed . 

     { b Note } Do { e not } use this function for creating an output which 
     writes to one or more underlying outputs . Rather , use { ! wrap_out } . 

    Fully create an output by giving all the needed functions.

    @param write  Write one character to the output (see {!write}).
    @param output Write a (sub)string to the output (see {!output}).
    @param flush  Flush any buffers of this output  (see {!flush}).
    @param close  Close this output. The output will be automatically
    flushed.

    {b Note} Do {e not} use this function for creating an output which
    writes to one or more underlying outputs. Rather, use {!wrap_out}.
*)

val inherit_out:
  ?write:(char -> unit) ->
  ?output:(Bytes.t -> int -> int -> int) ->
  ?flush:(unit -> unit) ->
  ?close:(unit -> unit) ->
  _ output -> unit output
* 
    Simplified and optimized version of { ! wrap_out } whenever only 
    one output appears as dependency . 

   Simplified and optimized version of {!wrap_out} whenever only
   one output appears as dependency.
*)


val wrap_out :
  write:(char -> unit)         ->
  output:(Bytes.t -> int -> int -> int) ->
  flush:(unit -> unit)         ->
  close:(unit -> 'a)           ->
  underlying:('b output list)  ->
  'a output
* 
    Fully create an output that writes to one or more underlying outputs . 

    This function is a more general version of { ! create_out } , 
    which also handles dependency management between outputs . 

    To illustrate the need for dependency management , let us consider 
    the following values : 
    - an output [ out ] 
    - a function [ f : _ output - > _ output ] , using { ! create_out } to 
    create a new output for writing some data to an underyling 
    output ( for instance , a function comparale to { ! tab_out } or a 
    function performing transparent compression or transparent 
    traduction between encodings ) 

    With these values , let us consider the following scenario 
    - a new output [ f out ] is created 
    - some data is written to [ f out ] but not flushed 
    - output [ out ] is closed , perhaps manually or as a consequence 
    of garbage - collection , or because the program has ended 
    - data written to [ f out ] is flushed . 

    In this case , data reaches [ out ] only after [ out ] has been closed , 
    which violates the protocol .   Despite appearances , it is quite easy 
    to reach such situation , especially in short programs . 

    The solution is to use [ wrap_out ] rather than [ create_out ] in [ f ] . 
    Specifying that [ f out ] writes on [ out ] will then let the run - time 
    flush and close [ f out ] when [ out ] is closed for any reason , which 
    in turn avoids the issue . 

    @param write   Write one character to the output ( see { ! write } ) . 
    @param output Write a ( sub)string to the output ( see { ! output } ) . 
    @param flush   Flush any buffers of this output   ( see { ! flush } ) . 
    @param close   Close this output . The output will be automatically 
    flushed . 
    @param underlying The list of outputs to which the new output will 
    write . 

    { b Note } Function [ close ] should { e not } close [ underlying ] 
    yourself . This is a common mistake which may cause sockets or 
    standard output to be closed while they are still being used by 
    another part of the program . 

   Fully create an output that writes to one or more underlying outputs.

   This function is a more general version of {!create_out},
   which also handles dependency management between outputs.

   To illustrate the need for dependency management, let us consider
   the following values:
   - an output [out]
   - a function [f : _ output -> _ output], using {!create_out} to
   create a new output for writing some data to an underyling
   output (for instance, a function comparale to {!tab_out} or a
   function performing transparent compression or transparent
   traduction between encodings)

   With these values, let us consider the following scenario
   - a new output [f out] is created
   - some data is written to [f out] but not flushed
   - output [out] is closed, perhaps manually or as a consequence
   of garbage-collection, or because the program has ended
   - data written to [f out] is flushed.

   In this case, data reaches [out] only after [out] has been closed,
   which violates the protocol.  Despite appearances, it is quite easy
   to reach such situation, especially in short programs.

   The solution is to use [wrap_out] rather than [create_out] in [f].
   Specifying that [f out] writes on [out] will then let the run-time
   flush and close [f out] when [out] is closed for any reason, which
   in turn avoids the issue.

   @param write  Write one character to the output (see {!write}).
   @param output Write a (sub)string to the output (see {!output}).
   @param flush  Flush any buffers of this output  (see {!flush}).
   @param close  Close this output. The output will be automatically
   flushed.
   @param underlying The list of outputs to which the new output will
   write.

   {b Note} Function [close] should {e not} close [underlying]
   yourself. This is a common mistake which may cause sockets or
   standard output to be closed while they are still being used by
   another part of the program.
*)

val default_buffer_size : int
(**The default size of buffers.*)


* { 6 Binary files API } 

     Here is some API useful for working with binary files , in particular 
     binary files generated by C applications . By default , encoding of 
     multibyte integers is low - endian . The BigEndian module provide multibyte 
     operations with other encoding . 


    Here is some API useful for working with binary files, in particular
    binary files generated by C applications. By default, encoding of
    multibyte integers is low-endian. The BigEndian module provide multibyte
    operations with other encoding.
*)

exception Overflow of string
(** Exception raised when a read or write operation cannot be completed. *)

val read_byte : input -> int
* Read an unsigned 8 - bit integer .

val read_signed_byte : input -> int
* Read an signed 8 - bit integer .

val read_ui16 : input -> int
* Read an unsigned 16 - bit word .

val read_i16 : input -> int
* Read a signed 16 - bit word .

val read_i32 : input -> int
* Read a signed 32 - bit integer . @raise Overflow if the 
     read integer can not be represented as an OCaml 31 - bit integer .
    read integer cannot be represented as an OCaml 31-bit integer. *)

val read_real_i32 : input -> int32
* Read a signed 32 - bit integer as an OCaml int32 .

val read_i64 : input -> int64
* Read a signed 64 - bit integer as an OCaml int64 .

val read_float : input -> float
* Read an IEEE single precision floating point value .

val read_double : input -> float
(** Read an IEEE double precision floating point value. *)

val read_string : input -> string
(** Read a null-terminated string. *)

val read_line : input -> string
(** Read a LF or CRLF terminated string. *)

val write_byte : 'a output -> int -> unit
* Write an unsigned 8 - bit byte .

val write_ui16 : 'a output -> int -> unit
* Write an unsigned 16 - bit word .

val write_i16 : 'a output -> int -> unit
* Write a signed 16 - bit word .

val write_i32 : 'a output -> int -> unit
* Write a signed 32 - bit integer .

val write_real_i32 : 'a output -> int32 -> unit
(** Write an OCaml int32. *)

val write_i64 : 'a output -> int64 -> unit
* Write an OCaml int64 .

val write_double : 'a output -> float -> unit
(** Write an IEEE double precision floating point value. *)

val write_float : 'a output -> float -> unit
* Write an IEEE single precision floating point value .

val write_string : 'a output -> string -> unit
(** Write a string and append an null character. *)

val write_line : 'a output -> string -> unit
(** Write a line and append a LF (it might be converted
    to CRLF on some systems depending on the underlying BatIO). *)

external cast_output : 'a output -> unit output = "%identity"
(** You can safely transform any output to an unit output in a safe way
    by using this function. *)

* 
    { 6 For compatibility purposes } 

   {6 For compatibility purposes}
*)

val input_channel : ?autoclose:bool -> ?cleanup:bool -> in_channel -> input
(** Create an input that will read from a channel.

    @param autoclose If true or unspecified, the {!type: input}
    will be automatically closed when the underlying [in_channel]
    has reached its end.

    @param cleanup If true, the channel
    will be automatically closed when the {!type: input} is closed.
    Otherwise, you will need to close the channel manually.
*)

val output_channel : ?cleanup:bool -> out_channel -> unit output
(** Create an output that will write into a channel.

    @param cleanup If true, the channel
    will be automatically closed when the {!type: output} is closed.
    Otherwise, you will need to close the channel manually.
*)
(*
val to_input_channel : input -> in_channel
(** Create a channel that will read from an input.

    {b Note} This function is very costly and is provided
    essentially for debugging purposes or for reusing legacy
    libraries which can't be adapted. As a general rule, if
    you can avoid using this function, don't use it.*)

val to_output_channel: _ output -> out_channel
(** Create a channel that will write to an output

    {b Note} This function is very costly and is provided
    essentially for debugging purposes or for reusing legacy
    libraries which can't be adapted. As a general rule, if
    you can avoid using this function, don't use it.*)
*)

* { 6 Standard inputs / outputs }

val stdin : input
(** Standard input, as per Unix/Windows conventions (by default, keyboard).*)

val stdout: unit output
(** Standard output, as per Unix/Windows conventions (by default, console).

    Use this output to display regular messages.*)

val stderr: unit output
(** Standard error output, as per Unix/Windows conventions.

    Use this output to display warnings and error messages.
*)

val stdnull: unit output
(** An output which discards everything written to it.

    Use this output to ignore messages.*)

* { 6 Comparison } 

     The following modules may be useful to create hashtables of inputs or outputs . 


    The following modules may be useful to create hashtables of inputs or outputs.
*)

module Input :
sig
  type t = input
  val compare : input -> input -> int
  (**A total order on inputs*)

  val hash    : input -> int
  (**A hash function for inputs*)

  val equal : input -> input -> bool
end

module Output :
sig
  type t = unit output
  val compare : _ output -> _ output -> int
  (**A total order on outputs*)

  val hash    : _ output -> int
  (**A hash function for outputs*)

  val equal : _ output -> _ output -> bool
end

(**/**)
* { 6 Internals }

external noop        : unit      -> unit        = "%ignore"

* 
    { 7 Optimized access to fields } 

   {7 Optimized access to fields}
*)

val get_output : _ output -> (Bytes.t -> int -> int -> int)
val get_flush  : _ output -> (unit -> unit)

val lock : BatConcurrent.lock ref
(**
   A reference to a set of locking operations.
*)


* 
    { 7 Facilities for debugging } 

   {7 Facilities for debugging}
*)

val get_output_id : _ output -> int
val get_input_id  : input -> int

  (**/**)

* This exception is raised when reading on a closed input. 
* This exception is raised when reading on a closed output. 
* Read a single char from an input or raise [No_more_input] if
    no input available. 
* read all the contents of the input until [No_more_input] is raised. 
* Create a pipe between an input and an output. Data written from
    the output can be read from the input. 
* [nread i n] reads a string of size up to [n] from an input.
    The function will raise [No_more_input] if no input is available.
    It will raise [Invalid_argument] if [n] < 0. 
* [really_nread i n] reads a string of exactly [n] characters
    from the input. @raise No_more_input if at least [n] characters are
    not available. @raise Invalid_argument if [n] < 0. 
* Close the input. It can no longer be read from. 
val auto_close_in : input -> input
  (** Create a new channel which will close automatically once there is nothing
    left to read.
* Write a single char to an output. 
* Write a string to an output. 
* Flush an output. 
* Flush all outputs. 
* Close the output and return its accumulator data.
    It can no longer be written. 
* Close all outputs.
    Ignore errors.
* Create an input that will read from a string. 
* Create an output that will write into a string in an efficient way.
    When closed, the output returns all the data written into it. 
*
   Register a function to be triggered just before an output is closed.

* Fully create an input reading from other inputs by giving all the needed functions.

    This function is a more general version of {!create_in}
    which also handles dependency management between inputs.

*The default size of buffers.
* Exception raised when a read or write operation cannot be completed. 
* Read an IEEE double precision floating point value. 
* Read a null-terminated string. 
* Read a LF or CRLF terminated string. 
* Write an OCaml int32. 
* Write an IEEE double precision floating point value. 
* Write a string and append an null character. 
* Write a line and append a LF (it might be converted
    to CRLF on some systems depending on the underlying BatIO). 
* You can safely transform any output to an unit output in a safe way
    by using this function. 
* Create an input that will read from a channel.

    @param autoclose If true or unspecified, the {!type: input}
    will be automatically closed when the underlying [in_channel]
    has reached its end.

    @param cleanup If true, the channel
    will be automatically closed when the {!type: input} is closed.
    Otherwise, you will need to close the channel manually.

* Create an output that will write into a channel.

    @param cleanup If true, the channel
    will be automatically closed when the {!type: output} is closed.
    Otherwise, you will need to close the channel manually.


val to_input_channel : input -> in_channel
(** Create a channel that will read from an input.

    {b Note} This function is very costly and is provided
    essentially for debugging purposes or for reusing legacy
    libraries which can't be adapted. As a general rule, if
    you can avoid using this function, don't use it.
* Create a channel that will write to an output

    {b Note} This function is very costly and is provided
    essentially for debugging purposes or for reusing legacy
    libraries which can't be adapted. As a general rule, if
    you can avoid using this function, don't use it.
* Standard input, as per Unix/Windows conventions (by default, keyboard).
* Standard output, as per Unix/Windows conventions (by default, console).

    Use this output to display regular messages.
* Standard error output, as per Unix/Windows conventions.

    Use this output to display warnings and error messages.

* An output which discards everything written to it.

    Use this output to ignore messages.
*A total order on inputs
*A hash function for inputs
*A total order on outputs
*A hash function for outputs
*/*
*
   A reference to a set of locking operations.

*/*

  * BatInnerIO - Abstract input / output ( inner module ) 
  * Copyright ( C ) 2003   
  *                2008   
  *                2008   
  * 
  * This library is free software ; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public 
  * License as published by the Free Software Foundation ; either 
  * version 2.1 of the License , or ( at your option ) any later version , 
  * with the special exception on linking described in file LICENSE . 
  * 
  * This library is distributed in the hope that it will be useful , 
  * but WITHOUT ANY WARRANTY ; without even the implied warranty of 
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .   See the GNU 
  * Lesser General Public License for more details . 
  * 
  * You should have received a copy of the GNU Lesser General Public 
  * License along with this library ; if not , write to the Free Software 
  * Foundation , Inc. , 59 Temple Place , Suite 330 , Boston , MA   02111 - 1307   USA 
 
 * BatInnerIO - Abstract input/output (inner module)
 * Copyright (C) 2003 Nicolas Cannasse
 *               2008 David Teller
 *               2008 Philippe Strauss
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version,
 * with the special exception on linking described in file LICENSE.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)


* 
    Core of the BatIO module . 

    This module contains the core definitions of { ! BatIO } , so as to avoid circular 
    dependencies between modules which only need simple functions of { ! BatIO } and 
    that module itself . 

    Do n't use this module , use { ! BatIO } . 

    @author   
    @author   
    @author   
    @author   

   Core of the BatIO module.

   This module contains the core definitions of {!BatIO}, so as to avoid circular
   dependencies between modules which only need simple functions of {!BatIO} and
   that module itself.

   Don't use this module, use {!BatIO}.

   @author Nicolas Cannasse
   @author David Teller
   @author Philippe Strauss
   @author Edgar Friendly
*)

type input
type 'a output

exception No_more_input
* This exception is raised when reading on an input with the [ read ] or 
     [ nread ] functions while there is no available token to read .
    [nread] functions while there is no available token to read. *)

exception Input_closed

exception Output_closed

val read : input -> char

val read_all : input -> string

val pipe : unit -> input * unit output

val nread : input -> int -> string

val really_nread : input -> int -> string

val input : input -> Bytes.t -> int -> int -> int
* [ input i s   ] reads up to [ len ] bytes from the given input , 
     storing them in byte sequence [ s ] , starting at position [ p ] . It 
     returns the actual number of bytes read or raise 
     [ No_more_input ] if no character can be read . It will raise 
     [ Invalid_argument ] if [ p ] and [ len ] do not designate a valid 
     subsequence of [ s ] .
    storing them in byte sequence [s], starting at position [p]. It
    returns the actual number of bytes read or raise
    [No_more_input] if no character can be read. It will raise
    [Invalid_argument] if [p] and [len] do not designate a valid
    subsequence of [s]. *)

val really_input : input -> Bytes.t -> int -> int -> int
* [ really_input i s   ] reads exactly [ len ] characters from the 
     given input , storing them in the byte sequence [ s ] , starting at 
     position [ p ] . For consistency with { ! BatIO.input } it returns 
     [ len ] . @raise No_more_input if at least [ len ] characters are not 
     available . @raise Invalid_argument if [ p ] and [ len ] do not designate 
     a valid subsequence of [ s ] .
    given input, storing them in the byte sequence [s], starting at
    position [p]. For consistency with {!BatIO.input} it returns
    [len]. @raise No_more_input if at least [len] characters are not
    available. @raise Invalid_argument if [p] and [len] do not designate
    a valid subsequence of [s]. *)

val close_in : input -> unit


val write : 'a output -> char -> unit

val nwrite : 'a output -> string -> unit

val nwrite_bytes : 'a output -> Bytes.t -> unit
* Write a byte sequence to an output . 

     @since 2.8.0

    @since 2.8.0 *)

val output : 'a output -> Bytes.t -> int -> int -> int
* [ output o s   ] writes up to [ len ] characters from byte 
     sequence [ len ] , starting at offset [ p ] . It returns the number of 
     characters written . It will raise [ Invalid_argument ] if [ p ] and 
     [ len ] do not designate a valid subsequence of [ s ] .
    sequence [len], starting at offset [p]. It returns the number of
    characters written. It will raise [Invalid_argument] if [p] and
    [len] do not designate a valid subsequence of [s]. *)

val output_substring : 'a output -> string -> int -> int -> int
* like [ output ] above , but outputs from a substring instead of 
     a subsequence of bytes 

     @since 2.8.0
    a subsequence of bytes

    @since 2.8.0 *)

val really_output : 'a output -> Bytes.t -> int -> int -> int
* [ really_output o s   ] writes exactly [ len ] characters from 
     byte sequence [ s ] onto the the output , starting with the character 
     at offset [ p ] . For consistency with { ! BatIO.output } it returns 
     [ len ] . @raise Invalid_argument if [ p ] and [ len ] do not designate 
     a valid subsequence of [ s ] .
    byte sequence [s] onto the the output, starting with the character
    at offset [p]. For consistency with {!BatIO.output} it returns
    [len]. @raise Invalid_argument if [p] and [len] do not designate
    a valid subsequence of [s]. *)

val really_output_substring : 'a output -> string -> int -> int -> int
* like [ really_output ] above , but outputs from a substring instead 
     of a subsequence of bytes 

     @since 2.8.0
    of a subsequence of bytes

    @since 2.8.0 *)

val flush : 'a output -> unit

val flush_all : unit -> unit

val close_out : 'a output -> 'a

val close_all : unit -> unit

val input_string : string -> input

val output_string : unit -> string output

val on_close_out : 'a output -> ('a output -> unit) -> unit

val create_in :
  read:(unit -> char) ->
  input:(Bytes.t -> int -> int -> int) ->
  close:(unit -> unit) -> input
* Fully create an input by giving all the needed functions . 

     { b Note } Do { e not } use this function for creating an input 
     which reads from one or more underlying inputs . Rather , use 
     { ! wrap_in } . 


    {b Note} Do {e not} use this function for creating an input
    which reads from one or more underlying inputs. Rather, use
    {!wrap_in}.
*)

val inherit_in:
  ?read:(unit -> char) ->
  ?input:(Bytes.t -> int -> int -> int) ->
  ?close:(unit -> unit) ->
  input -> input
* 
    Simplified and optimized version of { ! wrap_in } whenever only 
    one input appears as dependency . 

   Simplified and optimized version of {!wrap_in} whenever only
   one input appears as dependency.
*)


val wrap_in :
  read:(unit -> char) ->
  input:(Bytes.t -> int -> int -> int) ->
  close:(unit -> unit) ->
  underlying:(input list) ->
  input




val create_out :
  write:(char -> unit) ->
  output:(Bytes.t -> int -> int -> int) ->
  flush:(unit -> unit) ->
  close:(unit -> 'a) ->
  'a output
* 
     Fully create an output by giving all the needed functions . 

     @param write   Write one character to the output ( see { ! write } ) . 
     @param output Write a ( sub)string to the output ( see { ! output } ) . 
     @param flush   Flush any buffers of this output   ( see { ! flush } ) . 
     @param close   Close this output . The output will be automatically 
     flushed . 

     { b Note } Do { e not } use this function for creating an output which 
     writes to one or more underlying outputs . Rather , use { ! wrap_out } . 

    Fully create an output by giving all the needed functions.

    @param write  Write one character to the output (see {!write}).
    @param output Write a (sub)string to the output (see {!output}).
    @param flush  Flush any buffers of this output  (see {!flush}).
    @param close  Close this output. The output will be automatically
    flushed.

    {b Note} Do {e not} use this function for creating an output which
    writes to one or more underlying outputs. Rather, use {!wrap_out}.
*)

val inherit_out:
  ?write:(char -> unit) ->
  ?output:(Bytes.t -> int -> int -> int) ->
  ?flush:(unit -> unit) ->
  ?close:(unit -> unit) ->
  _ output -> unit output
* 
    Simplified and optimized version of { ! wrap_out } whenever only 
    one output appears as dependency . 

   Simplified and optimized version of {!wrap_out} whenever only
   one output appears as dependency.
*)


val wrap_out :
  write:(char -> unit)         ->
  output:(Bytes.t -> int -> int -> int) ->
  flush:(unit -> unit)         ->
  close:(unit -> 'a)           ->
  underlying:('b output list)  ->
  'a output
* 
    Fully create an output that writes to one or more underlying outputs . 

    This function is a more general version of { ! create_out } , 
    which also handles dependency management between outputs . 

    To illustrate the need for dependency management , let us consider 
    the following values : 
    - an output [ out ] 
    - a function [ f : _ output - > _ output ] , using { ! create_out } to 
    create a new output for writing some data to an underyling 
    output ( for instance , a function comparale to { ! tab_out } or a 
    function performing transparent compression or transparent 
    traduction between encodings ) 

    With these values , let us consider the following scenario 
    - a new output [ f out ] is created 
    - some data is written to [ f out ] but not flushed 
    - output [ out ] is closed , perhaps manually or as a consequence 
    of garbage - collection , or because the program has ended 
    - data written to [ f out ] is flushed . 

    In this case , data reaches [ out ] only after [ out ] has been closed , 
    which violates the protocol .   Despite appearances , it is quite easy 
    to reach such situation , especially in short programs . 

    The solution is to use [ wrap_out ] rather than [ create_out ] in [ f ] . 
    Specifying that [ f out ] writes on [ out ] will then let the run - time 
    flush and close [ f out ] when [ out ] is closed for any reason , which 
    in turn avoids the issue . 

    @param write   Write one character to the output ( see { ! write } ) . 
    @param output Write a ( sub)string to the output ( see { ! output } ) . 
    @param flush   Flush any buffers of this output   ( see { ! flush } ) . 
    @param close   Close this output . The output will be automatically 
    flushed . 
    @param underlying The list of outputs to which the new output will 
    write . 

    { b Note } Function [ close ] should { e not } close [ underlying ] 
    yourself . This is a common mistake which may cause sockets or 
    standard output to be closed while they are still being used by 
    another part of the program . 

   Fully create an output that writes to one or more underlying outputs.

   This function is a more general version of {!create_out},
   which also handles dependency management between outputs.

   To illustrate the need for dependency management, let us consider
   the following values:
   - an output [out]
   - a function [f : _ output -> _ output], using {!create_out} to
   create a new output for writing some data to an underyling
   output (for instance, a function comparale to {!tab_out} or a
   function performing transparent compression or transparent
   traduction between encodings)

   With these values, let us consider the following scenario
   - a new output [f out] is created
   - some data is written to [f out] but not flushed
   - output [out] is closed, perhaps manually or as a consequence
   of garbage-collection, or because the program has ended
   - data written to [f out] is flushed.

   In this case, data reaches [out] only after [out] has been closed,
   which violates the protocol.  Despite appearances, it is quite easy
   to reach such situation, especially in short programs.

   The solution is to use [wrap_out] rather than [create_out] in [f].
   Specifying that [f out] writes on [out] will then let the run-time
   flush and close [f out] when [out] is closed for any reason, which
   in turn avoids the issue.

   @param write  Write one character to the output (see {!write}).
   @param output Write a (sub)string to the output (see {!output}).
   @param flush  Flush any buffers of this output  (see {!flush}).
   @param close  Close this output. The output will be automatically
   flushed.
   @param underlying The list of outputs to which the new output will
   write.

   {b Note} Function [close] should {e not} close [underlying]
   yourself. This is a common mistake which may cause sockets or
   standard output to be closed while they are still being used by
   another part of the program.
*)

val default_buffer_size : int


* { 6 Binary files API } 

     Here is some API useful for working with binary files , in particular 
     binary files generated by C applications . By default , encoding of 
     multibyte integers is low - endian . The BigEndian module provide multibyte 
     operations with other encoding . 


    Here is some API useful for working with binary files, in particular
    binary files generated by C applications. By default, encoding of
    multibyte integers is low-endian. The BigEndian module provide multibyte
    operations with other encoding.
*)

exception Overflow of string

val read_byte : input -> int
* Read an unsigned 8 - bit integer .

val read_signed_byte : input -> int
* Read an signed 8 - bit integer .

val read_ui16 : input -> int
* Read an unsigned 16 - bit word .

val read_i16 : input -> int
* Read a signed 16 - bit word .

val read_i32 : input -> int
* Read a signed 32 - bit integer . @raise Overflow if the 
     read integer can not be represented as an OCaml 31 - bit integer .
    read integer cannot be represented as an OCaml 31-bit integer. *)

val read_real_i32 : input -> int32
* Read a signed 32 - bit integer as an OCaml int32 .

val read_i64 : input -> int64
* Read a signed 64 - bit integer as an OCaml int64 .

val read_float : input -> float
* Read an IEEE single precision floating point value .

val read_double : input -> float

val read_string : input -> string

val read_line : input -> string

val write_byte : 'a output -> int -> unit
* Write an unsigned 8 - bit byte .

val write_ui16 : 'a output -> int -> unit
* Write an unsigned 16 - bit word .

val write_i16 : 'a output -> int -> unit
* Write a signed 16 - bit word .

val write_i32 : 'a output -> int -> unit
* Write a signed 32 - bit integer .

val write_real_i32 : 'a output -> int32 -> unit

val write_i64 : 'a output -> int64 -> unit
* Write an OCaml int64 .

val write_double : 'a output -> float -> unit

val write_float : 'a output -> float -> unit
* Write an IEEE single precision floating point value .

val write_string : 'a output -> string -> unit

val write_line : 'a output -> string -> unit

external cast_output : 'a output -> unit output = "%identity"

* 
    { 6 For compatibility purposes } 

   {6 For compatibility purposes}
*)

val input_channel : ?autoclose:bool -> ?cleanup:bool -> in_channel -> input

val output_channel : ?cleanup:bool -> out_channel -> unit output

val to_output_channel: _ output -> out_channel
*)

* { 6 Standard inputs / outputs }

val stdin : input

val stdout: unit output

val stderr: unit output

val stdnull: unit output

* { 6 Comparison } 

     The following modules may be useful to create hashtables of inputs or outputs . 


    The following modules may be useful to create hashtables of inputs or outputs.
*)

module Input :
sig
  type t = input
  val compare : input -> input -> int

  val hash    : input -> int

  val equal : input -> input -> bool
end

module Output :
sig
  type t = unit output
  val compare : _ output -> _ output -> int

  val hash    : _ output -> int

  val equal : _ output -> _ output -> bool
end

* { 6 Internals }

external noop        : unit      -> unit        = "%ignore"

* 
    { 7 Optimized access to fields } 

   {7 Optimized access to fields}
*)

val get_output : _ output -> (Bytes.t -> int -> int -> int)
val get_flush  : _ output -> (unit -> unit)

val lock : BatConcurrent.lock ref


* 
    { 7 Facilities for debugging } 

   {7 Facilities for debugging}
*)

val get_output_id : _ output -> int
val get_input_id  : input -> int

