Persistent patterns, save and load to a file.
[ocaml-bitstring.git] / bitmatch.mli
index f1c7ed1..95cc63c 100644 (file)
@@ -15,7 +15,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  *
- * $Id: bitmatch.mli,v 1.16 2008-04-25 12:55:39 rjones Exp $
+ * $Id$
  *)
 
 (**
@@ -29,7 +29,7 @@
    this module to both parse and generate binary formats, for
    example, communications protocols, disk formats and binary files.
 
-   {{:http://et.redhat.com/~rjones/bitmatch/}OCaml bitmatch website}
+   {{:http://code.google.com/p/bitmatch/}OCaml bitmatch website}
 
    {2 Examples}
 
@@ -186,7 +186,7 @@ let make_message typ subtype param =
    match then the standard library [Match_failure] exception is
    thrown.
 
-   Patterns look a bit different from normal match patterns.  The
+   Patterns look a bit different from normal match patterns.  They
    consist of a list of bitfields separated by [;] where each bitfield
    contains a bind variable, the width (in bits) of the field, and
    other information.  Some example patterns:
@@ -290,17 +290,21 @@ bitmatch bits with
    A bitstring field of length 0 matches an empty bitstring
    (occasionally useful when matching optional subfields).
 
-   Qualifiers are a list of identifiers which control the type,
+   Qualifiers are a list of identifiers/expressions which control the type,
    signedness and endianness of the field.  Permissible qualifiers are:
 
-   - [int] (field has an integer type)
-   - [string] (field is a string type)
-   - [bitstring] (field is a bitstring type)
-   - [signed] (field is signed)
-   - [unsigned] (field is unsigned)
-   - [bigendian] (field is big endian - a.k.a network byte order)
-   - [littleendian] (field is little endian - a.k.a Intel byte order)
-   - [nativeendian] (field is same endianness as the machine)
+   - [int]: field has an integer type
+   - [string]: field is a string type
+   - [bitstring]: field is a bitstring type
+   - [signed]: field is signed
+   - [unsigned]: field is unsigned
+   - [bigendian]: field is big endian - a.k.a network byte order
+   - [littleendian]: field is little endian - a.k.a Intel byte order
+   - [nativeendian]: field is same endianness as the machine
+   - [endian (expr)]: [expr] should be an expression which evaluates to
+       a {!endian} type, ie. [LittleEndian], [BigEndian] or [NativeEndian].
+       The expression is an arbitrary OCaml expression and can use the
+       value of earlier fields in the bitmatch.
 
    The default settings are [int], [unsigned], [bigendian].
 
@@ -381,9 +385,8 @@ Bitmatch.hexdump_bitstring stdout bits ;;
    computed expression.
 
    Detection of compile-time constants is quite simplistic so only an
-   immediate, simple integer is recognised as a constant and anything
-   else is considered a computed expression, even expressions such as
-   [5-2] which are obviously (to our eyes) constant.
+   simple integer literals and simple expressions (eg. [5*8]) are
+   recognized as constants.
 
    In any case the bit size of an integer is limited to the range
    \[1..64\].  This is detected as a compile-time error if that is
@@ -414,6 +417,10 @@ Bitmatch.hexdump_bitstring stdout bits ;;
    still need to be a runtime check to enforce the
    size).
 
+   {2 Named patterns and persistent patterns}
+
+   Please see {!Bitmatch_persistent} for documentation on this subject.
+
    {2 Compiling}
 
    Using the compiler directly you can do:
@@ -527,19 +534,26 @@ Bitmatch.hexdump_bitstring stdout bits ;;
    {3 Types}
 *)
 
+type endian = BigEndian | LittleEndian | NativeEndian
+
+val string_of_endian : endian -> string
+(** Endianness. *)
+
 type bitstring = string * int * int
 (** [bitstring] is the basic type used to store bitstrings.
 
     The type contains the underlying data (a string),
     the current bit offset within the string and the
     current bit length of the string (counting from the
-    bit offset).  Note that the offsets are bits, not bytes.
+    bit offset).  Note that the offset and length are
+    in {b bits}, not bytes.
 
     Normally you don't need to use the bitstring type
     directly, since there are functions and syntax
     extensions which hide the details.
-    See {!bitstring_of_file}, {!hexdump_bitstring},
-    {!bitstring_length}.
+
+    See also {!bitstring_of_string}, {!bitstring_of_file},
+    {!hexdump_bitstring}, {!bitstring_length}.
 *)
 
 (** {3 Exceptions} *)
@@ -576,22 +590,46 @@ val make_bitstring : int -> char -> bitstring
 
     Note that the length is in bits, not bytes. *)
 
+val bitstring_of_string : string -> bitstring
+(** [bitstring_of_string str] creates a bitstring
+    of length [String.length str * 8] (bits) containing the
+    bits in [str].
+
+    Note that the bitstring uses [str] as the underlying
+    string (see the representation of {!bitstring}) so you
+    should not change [str] after calling this. *)
+
+val bitstring_of_file : string -> bitstring
+(** [bitstring_of_file filename] loads the named file
+    into a bitstring. *)
+
 val bitstring_of_chan : in_channel -> bitstring
 (** [bitstring_of_chan chan] loads the contents of
     the input channel [chan] as a bitstring.
 
     The length of the final bitstring is determined
     by the remaining input in [chan], but will always
-    be a multiple of 8 bits. *)
+    be a multiple of 8 bits.
 
-val bitstring_of_file : string -> bitstring
-(** [bitstring_of_file filename] loads the named file
-    into a bitstring. *)
+    See also {!bitstring_of_chan_max}. *)
 
-val hexdump_bitstring : out_channel -> bitstring -> unit
-(** [hexdump_bitstring chan bitstring] prints the bitstring
-    to the output channel in a format similar to the
-    Unix command [hexdump -C]. *)
+val bitstring_of_chan_max : in_channel -> int -> bitstring
+(** [bitstring_of_chan_max chan max] works like
+    {!bitstring_of_chan} but will only read up to
+    [max] bytes from the channel (or fewer if the end of input
+    occurs before that). *)
+
+val bitstring_of_file_descr : Unix.file_descr -> bitstring
+(** [bitstring_of_file_descr fd] loads the contents of
+    the file descriptor [fd] as a bitstring.
+
+    See also {!bitstring_of_chan}, {!bitstring_of_file_descr_max}. *)
+
+val bitstring_of_file_descr_max : Unix.file_descr -> int -> bitstring
+(** [bitstring_of_file_descr_max fd max] works like
+    {!bitstring_of_file_descr} but will only read up to
+    [max] bytes from the channel (or fewer if the end of input
+    occurs before that). *)
 
 val bitstring_length : bitstring -> int
 (** [bitstring_length bitstring] returns the length of
@@ -604,7 +642,42 @@ val string_of_bitstring : bitstring -> string
     This function is inefficient.  In the best case when the bitstring
     is nicely byte-aligned we do a [String.sub] operation.  If the
     bitstring isn't aligned then this involves a lot of bit twiddling
-    and is particularly inefficient. *)
+    and is particularly inefficient.
+
+    If the bitstring is not a multiple of 8 bits wide then the
+    final byte of the string contains the high bits set to the
+    remaining bits and the low bits set to 0. *)
+
+val bitstring_to_file : bitstring -> string -> unit
+(** [bitstring_to_file bits filename] writes the bitstring [bits]
+    to the file [filename].  It overwrites the output file.
+
+    Some restrictions apply, see {!bitstring_to_chan}. *)
+
+val bitstring_to_chan : bitstring -> out_channel -> unit
+(** [bitstring_to_file bits filename] writes the bitstring [bits]
+    to the channel [chan].
+
+    Channels are made up of bytes, bitstrings can be any bit length
+    including fractions of bytes.  So this function only works
+    if the length of the bitstring is an exact multiple of 8 bits
+    (otherwise it raises [Invalid_argument "bitstring_to_chan"]).
+
+    Furthermore the function is efficient only in the case where
+    the bitstring is stored fully aligned, otherwise it has to
+    do inefficient bit twiddling like {!string_of_bitstring}.
+
+    In the common case where the bitstring was generated by the
+    [BITSTRING] operator and is an exact multiple of 8 bits wide,
+    then this function will always work efficiently.
+*)
+
+(** {3 Printing bitstrings} *)
+
+val hexdump_bitstring : out_channel -> bitstring -> unit
+(** [hexdump_bitstring chan bitstring] prints the bitstring
+    to the output channel in a format similar to the
+    Unix command [hexdump -C]. *)
 
 (** {3 Bitstring buffer} *)
 
@@ -622,6 +695,12 @@ end
 
 (** {3 Miscellaneous} *)
 
+val package : string
+(** The package name, always ["ocaml-bitmatch"] *)
+
+val version : string
+(** The package version as a string. *)
+
 val debug : bool ref
 (** Set this variable to true to enable extended debugging.
     This only works if debugging was also enabled in the
@@ -646,16 +725,46 @@ val extract_int_be_unsigned : string -> int -> int -> int -> int * int * int
 
 val extract_int_le_unsigned : string -> int -> int -> int -> int * int * int
 
+val extract_int_ne_unsigned : string -> int -> int -> int -> int * int * int
+
+val extract_int_ee_unsigned : endian -> string -> int -> int -> int -> int * int * int
+
 val extract_int32_be_unsigned : string -> int -> int -> int -> int32 * int * int
 
 val extract_int32_le_unsigned : string -> int -> int -> int -> int32 * int * int
 
+val extract_int32_ne_unsigned : string -> int -> int -> int -> int32 * int * int
+
+val extract_int32_ee_unsigned : endian -> string -> int -> int -> int -> int32 * int * int
+
 val extract_int64_be_unsigned : string -> int -> int -> int -> int64 * int * int
 
-val construct_bit : Buffer.t -> bool -> int -> unit
+val extract_int64_le_unsigned : string -> int -> int -> int -> int64 * int * int
+
+val extract_int64_ne_unsigned : string -> int -> int -> int -> int64 * int * int
+
+val extract_int64_ee_unsigned : endian -> string -> int -> int -> int -> int64 * int * int
+
+val construct_bit : Buffer.t -> bool -> int -> exn -> unit
 
 val construct_char_unsigned : Buffer.t -> int -> int -> exn -> unit
 
 val construct_int_be_unsigned : Buffer.t -> int -> int -> exn -> unit
 
+val construct_int_ne_unsigned : Buffer.t -> int -> int -> exn -> unit
+
+val construct_int_ee_unsigned : endian -> Buffer.t -> int -> int -> exn -> unit
+
+val construct_int32_be_unsigned : Buffer.t -> int32 -> int -> exn -> unit
+
+val construct_int32_ne_unsigned : Buffer.t -> int32 -> int -> exn -> unit
+
+val construct_int32_ee_unsigned : endian -> Buffer.t -> int32 -> int -> exn -> unit
+
 val construct_int64_be_unsigned : Buffer.t -> int64 -> int -> exn -> unit
+
+val construct_int64_ne_unsigned : Buffer.t -> int64 -> int -> exn -> unit
+
+val construct_int64_ee_unsigned : endian -> Buffer.t -> int64 -> int -> exn -> unit
+
+val construct_string : Buffer.t -> string -> unit