Add signed int extract and construction functions, and test.
[ocaml-bitstring.git] / bitstring.mli
index 800cadd..501e6fb 100644 (file)
@@ -1,4 +1,4 @@
-(** Bitmatch library. *)
+(** Bitstring library. *)
 (* Copyright (C) 2008 Red Hat Inc., Richard W.M. Jones
  *
  * This library is free software; you can redistribute it and/or
 
    {2 Introduction}
 
-   Bitmatch adds Erlang-style bitstrings and matching over bitstrings
+   Bitstring adds Erlang-style bitstrings and matching over bitstrings
    as a syntax extension and library for OCaml.  You can use
    this module to both parse and generate binary formats, for
    example, communications protocols, disk formats and binary files.
 
-   {{:http://code.google.com/p/bitmatch/}OCaml bitmatch website}
+   {{:http://code.google.com/p/bitstring/}OCaml bitstring website}
+
+   This library used to be called "bitmatch".
 
    {2 Examples}
 
@@ -76,9 +78,9 @@ let display pkt =
     printf "  checksum: %d\n" checksum;
     printf "  source: %lx  dest: %lx\n" source dest;
     printf "  header options + padding:\n";
-    Bitmatch.hexdump_bitstring stdout options;
+    Bitstring.hexdump_bitstring stdout options;
     printf "  packet payload:\n";
-    Bitmatch.hexdump_bitstring stdout payload
+    Bitstring.hexdump_bitstring stdout payload
 
   | { version : 4 } ->
     eprintf "unknown IP version %d\n" version;
@@ -86,7 +88,7 @@ let display pkt =
 
   | { _ } as pkt ->
     eprintf "data is smaller than one nibble:\n";
-    Bitmatch.hexdump_bitstring stderr pkt;
+    Bitstring.hexdump_bitstring stderr pkt;
     exit 1
 ]}
 
@@ -94,7 +96,7 @@ let display pkt =
    {{:http://lxr.linux.no/linux/include/linux/ext3_fs.h}Linux EXT3 filesystem superblocks}:
 
 {[
-let bits = Bitmatch.bitstring_of_file "tests/ext3_sb"
+let bits = Bitstring.bitstring_of_file "tests/ext3_sb"
 
 let () =
   bitmatch bits with
@@ -241,7 +243,7 @@ bitmatch bits with
 {[
 | { n : 4;
     rest : -1 : bitstring }
-    when Bitmatch.bitstring_length rest = 0 -> ...
+    when Bitstring.bitstring_length rest = 0 -> ...
 
    (* Only matches exactly 4 bits. *)
 ]}
@@ -348,7 +350,7 @@ let bits =
       the integer 1, and the following 12 bits containing the integer 10,
       arranged in network byte order. *)
 
-Bitmatch.hexdump_bitstring stdout bits ;;
+Bitstring.hexdump_bitstring stdout bits ;;
 
    (* Prints:
 
@@ -526,24 +528,24 @@ bitmatch bits with
 
    {2 Named patterns and persistent patterns}
 
-   Please see {!Bitmatch_persistent} for documentation on this subject.
+   Please see {!Bitstring_persistent} for documentation on this subject.
 
    {2 Compiling}
 
    Using the compiler directly you can do:
 
    {v
-   ocamlc -I +bitmatch \
-     -pp "camlp4of bitmatch.cma bitmatch_persistent.cma \
-            `ocamlc -where`/bitmatch/pa_bitmatch.cmo" \
-     unix.cma bitmatch.cma test.ml -o test
+   ocamlc -I +bitstring \
+     -pp "camlp4of bitstring.cma bitstring_persistent.cma \
+            `ocamlc -where`/bitstring/pa_bitstring.cmo" \
+     unix.cma bitstring.cma test.ml -o test
    v}
 
    Simpler method using findlib:
 
    {v
    ocamlfind ocamlc \
-     -package bitmatch,bitmatch.syntax -syntax bitmatch.syntax \
+     -package bitstring,bitstring.syntax -syntax bitstring.syntax \
      -linkpkg test.ml -o test
    v}
 
@@ -578,7 +580,7 @@ bitmatch bits with
 
    However the above does not necessarily apply to strings used in
    matching, since they may cause the library to use the
-   {!Bitmatch.string_of_bitstring} function, which allocates a string.
+   {!Bitstring.string_of_bitstring} function, which allocates a string.
    So you should take care if you use the [string] type particularly
    with a computed length that is derived from external input.
 
@@ -611,9 +613,10 @@ bitmatch bits with
    Note that the when-clause is evaluated {i last}, so if you are
    relying on the when-clause to filter cases then your code may do a
    lot of extra and unncessary pattern-matching work on fields which
-   may never be needed just to evaluate the when-clause.  You can
-   usually rearrange the code to do only the first part of the match,
-   followed by the when-clause, followed by a second inner bitmatch.
+   may never be needed just to evaluate the when-clause.  Either
+   rearrange the code to do only the first part of the match,
+   followed by the when-clause, followed by a second inner bitmatch,
+   or use a [check()] qualifier within fields.
 
    {3 Safety}
 
@@ -664,6 +667,12 @@ type bitstring = string * int * int
     {!hexdump_bitstring}, {!bitstring_length}.
 *)
 
+type t = bitstring
+(** [t] is a synonym for the {!bitstring} type.
+
+    This allows you to use this module with functors like
+    [Set] and [Map] from the stdlib. *)
+
 (** {3 Exceptions} *)
 
 exception Construct_failure of string * string * int * int
@@ -680,6 +689,30 @@ exception Construct_failure of string * string * int * int
     location of the [BITSTRING] constructor that failed.
 *)
 
+(** {3 Bitstring comparison} *)
+
+val compare : bitstring -> bitstring -> int
+(** [compare bs1 bs2] compares two bitstrings and returns zero
+    if they are equal, a negative number if [bs1 < bs2], or a
+    positive number if [bs1 > bs2].
+
+    This tests "semantic equality" which is not affected by
+    the offset or alignment of the underlying representation
+    (see {!bitstring}).
+
+    The ordering is total and lexicographic. *)
+
+val equals : bitstring -> bitstring -> bool
+(** [equals] returns true if and only if the two bitstrings are
+    semantically equal.  It is the same as calling [compare] and
+    testing if the result is [0], but usually more efficient. *)
+
+val is_zeroes_bitstring : bitstring -> bool
+(** Tests if the bitstring is all zero bits (cf. {!zeroes_bitstring}) *)
+
+val is_ones_bitstring : bitstring -> bool
+(** Tests if the bitstring is all one bits (cf. {!ones_bitstring}). *)
+
 (** {3 Bitstring manipulation} *)
 
 val bitstring_length : bitstring -> int
@@ -719,6 +752,10 @@ val takebits : int -> bitstring -> bitstring
     Note that this function just changes the offset and length
     fields of the {!bitstring} tuple, so is very efficient. *)
 
+val concat : bitstring list -> bitstring
+(** Concatenate a list of bitstrings together into a single
+    bitstring. *)
+
 (** {3 Constructing bitstrings} *)
 
 val empty_bitstring : bitstring
@@ -847,10 +884,40 @@ end
     may also be useful for end users.  They work much like the
     standard library [Buffer] module. *)
 
+(** {3 Get/set bits}
+
+    These functions let you manipulate individual bits in the
+    bitstring.  However they are not particularly efficient and you
+    should generally use the [bitmatch] and [BITSTRING] operators when
+    building and parsing bitstrings.
+
+    These functions all raise [Invalid_argument "index out of bounds"]
+    if the index is out of range of the bitstring.
+*)
+
+val set : bitstring -> int -> unit
+  (** [set bits n] sets the [n]th bit in the bitstring to 1. *)
+
+val clear : bitstring -> int -> unit
+  (** [clear bits n] sets the [n]th bit in the bitstring to 0. *)
+
+val is_set : bitstring -> int -> bool
+  (** [is_set bits n] is true if the [n]th bit is set to 1. *)
+
+val is_clear : bitstring -> int -> bool
+  (** [is_clear bits n] is true if the [n]th bit is set to 0. *)
+
+val put : bitstring -> int -> int -> unit
+  (** [put bits n v] sets the [n]th bit in the bitstring to 1
+      if [v] is not zero, or to 0 if [v] is zero. *)
+
+val get : bitstring -> int -> int
+  (** [get bits n] returns the [n]th bit (returns non-zero or 0). *)
+
 (** {3 Miscellaneous} *)
 
 val package : string
-(** The package name, always ["ocaml-bitmatch"] *)
+(** The package name, always ["ocaml-bitstring"] *)
 
 val version : string
 (** The package version as a string. *)
@@ -858,7 +925,7 @@ val version : string
 val debug : bool ref
 (** Set this variable to true to enable extended debugging.
     This only works if debugging was also enabled in the
-    [pa_bitmatch.ml] file at compile time, otherwise it
+    [pa_bitstring.ml] file at compile time, otherwise it
     does nothing. *)
 
 (**/**)
@@ -867,56 +934,169 @@ val debug : bool ref
  * these directly - they are not safe.
  *)
 
-val extract_bitstring : string -> int -> int -> int -> bitstring * int * int
+(* 'extract' functions are used in bitmatch statements. *)
+
+val extract_bit : string -> int -> int -> int -> bool
+
+val extract_char_unsigned : string -> int -> int -> int -> int
+
+val extract_char_signed : string -> int -> int -> int -> int
+
+val extract_int_be_unsigned : string -> int -> int -> int -> int
+
+val extract_int_be_signed : string -> int -> int -> int -> int
+
+val extract_int_le_unsigned : string -> int -> int -> int -> int
+
+val extract_int_le_signed : string -> int -> int -> int -> int
+
+val extract_int_ne_unsigned : string -> int -> int -> int -> int
+
+val extract_int_ne_signed : string -> int -> int -> int -> int
+
+val extract_int_ee_unsigned : endian -> string -> int -> int -> int -> int
+
+val extract_int_ee_signed : endian -> string -> int -> int -> int -> int
+
+val extract_int32_be_unsigned : string -> int -> int -> int -> int32
+
+val extract_int32_le_unsigned : string -> int -> int -> int -> int32
+
+val extract_int32_ne_unsigned : string -> int -> int -> int -> int32
+
+val extract_int32_ee_unsigned : endian -> string -> int -> int -> int -> int32
+
+val extract_int64_be_unsigned : string -> int -> int -> int -> int64
+
+val extract_int64_le_unsigned : string -> int -> int -> int -> int64
+
+val extract_int64_ne_unsigned : string -> int -> int -> int -> int64
+
+val extract_int64_ee_unsigned : endian -> string -> int -> int -> int -> int64
 
-val extract_remainder : string -> int -> int -> bitstring * int * int
+external extract_fastpath_int16_be_unsigned : string -> int -> int = "ocaml_bitstring_extract_fastpath_int16_be_unsigned" "noalloc"
 
-val extract_bit : string -> int -> int -> int -> bool * int * int
+external extract_fastpath_int16_le_unsigned : string -> int -> int = "ocaml_bitstring_extract_fastpath_int16_le_unsigned" "noalloc"
 
-val extract_char_unsigned : string -> int -> int -> int -> int * int * int
+external extract_fastpath_int16_ne_unsigned : string -> int -> int = "ocaml_bitstring_extract_fastpath_int16_ne_unsigned" "noalloc"
 
-val extract_int_be_unsigned : string -> int -> int -> int -> int * int * int
+external extract_fastpath_int16_be_signed : string -> int -> int = "ocaml_bitstring_extract_fastpath_int16_be_signed" "noalloc"
 
-val extract_int_le_unsigned : string -> int -> int -> int -> int * int * int
+external extract_fastpath_int16_le_signed : string -> int -> int = "ocaml_bitstring_extract_fastpath_int16_le_signed" "noalloc"
 
-val extract_int_ne_unsigned : string -> int -> int -> int -> int * int * int
+external extract_fastpath_int16_ne_signed : string -> int -> int = "ocaml_bitstring_extract_fastpath_int16_ne_signed" "noalloc"
 
-val extract_int_ee_unsigned : endian -> string -> int -> int -> int -> int * int * int
+(*
+external extract_fastpath_int24_be_unsigned : string -> int -> int = "ocaml_bitstring_extract_fastpath_int24_be_unsigned" "noalloc"
+
+external extract_fastpath_int24_le_unsigned : string -> int -> int = "ocaml_bitstring_extract_fastpath_int24_le_unsigned" "noalloc"
+
+external extract_fastpath_int24_ne_unsigned : string -> int -> int = "ocaml_bitstring_extract_fastpath_int24_ne_unsigned" "noalloc"
+
+external extract_fastpath_int24_be_signed : string -> int -> int = "ocaml_bitstring_extract_fastpath_int24_be_signed" "noalloc"
+
+external extract_fastpath_int24_le_signed : string -> int -> int = "ocaml_bitstring_extract_fastpath_int24_le_signed" "noalloc"
+
+external extract_fastpath_int24_ne_signed : string -> int -> int = "ocaml_bitstring_extract_fastpath_int24_ne_signed" "noalloc"
+*)
+
+external extract_fastpath_int32_be_unsigned : string -> int -> int32 -> int32 = "ocaml_bitstring_extract_fastpath_int32_be_unsigned" "noalloc"
+
+external extract_fastpath_int32_le_unsigned : string -> int -> int32 -> int32 = "ocaml_bitstring_extract_fastpath_int32_le_unsigned" "noalloc"
+
+external extract_fastpath_int32_ne_unsigned : string -> int -> int32 -> int32 = "ocaml_bitstring_extract_fastpath_int32_ne_unsigned" "noalloc"
+
+external extract_fastpath_int32_be_signed : string -> int -> int32 -> int32 = "ocaml_bitstring_extract_fastpath_int32_be_signed" "noalloc"
+
+external extract_fastpath_int32_le_signed : string -> int -> int32 -> int32 = "ocaml_bitstring_extract_fastpath_int32_le_signed" "noalloc"
+
+external extract_fastpath_int32_ne_signed : string -> int -> int32 -> int32 = "ocaml_bitstring_extract_fastpath_int32_ne_signed" "noalloc"
+
+(*
+external extract_fastpath_int40_be_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int40_be_unsigned" "noalloc"
+
+external extract_fastpath_int40_le_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int40_le_unsigned" "noalloc"
+
+external extract_fastpath_int40_ne_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int40_ne_unsigned" "noalloc"
+
+external extract_fastpath_int40_be_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int40_be_signed" "noalloc"
+
+external extract_fastpath_int40_le_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int40_le_signed" "noalloc"
+
+external extract_fastpath_int40_ne_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int40_ne_signed" "noalloc"
 
-val extract_int32_be_unsigned : string -> int -> int -> int -> int32 * int * int
+external extract_fastpath_int48_be_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int48_be_unsigned" "noalloc"
 
-val extract_int32_le_unsigned : string -> int -> int -> int -> int32 * int * int
+external extract_fastpath_int48_le_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int48_le_unsigned" "noalloc"
 
-val extract_int32_ne_unsigned : string -> int -> int -> int -> int32 * int * int
+external extract_fastpath_int48_ne_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int48_ne_unsigned" "noalloc"
 
-val extract_int32_ee_unsigned : endian -> string -> int -> int -> int -> int32 * int * int
+external extract_fastpath_int48_be_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int48_be_signed" "noalloc"
 
-val extract_int64_be_unsigned : string -> int -> int -> int -> int64 * int * int
+external extract_fastpath_int48_le_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int48_le_signed" "noalloc"
 
-val extract_int64_le_unsigned : string -> int -> int -> int -> int64 * int * int
+external extract_fastpath_int48_ne_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int48_ne_signed" "noalloc"
 
-val extract_int64_ne_unsigned : string -> int -> int -> int -> int64 * int * int
+external extract_fastpath_int56_be_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int56_be_unsigned" "noalloc"
 
-val extract_int64_ee_unsigned : endian -> string -> int -> int -> int -> int64 * int * int
+external extract_fastpath_int56_le_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int56_le_unsigned" "noalloc"
 
+external extract_fastpath_int56_ne_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int56_ne_unsigned" "noalloc"
+
+external extract_fastpath_int56_be_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int56_be_signed" "noalloc"
+
+external extract_fastpath_int56_le_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int56_le_signed" "noalloc"
+
+external extract_fastpath_int56_ne_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int56_ne_signed" "noalloc"
+*)
+
+external extract_fastpath_int64_be_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int64_be_unsigned" "noalloc"
+
+external extract_fastpath_int64_le_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int64_le_unsigned" "noalloc"
+
+external extract_fastpath_int64_ne_unsigned : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int64_ne_unsigned" "noalloc"
+
+external extract_fastpath_int64_be_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int64_be_signed" "noalloc"
+
+external extract_fastpath_int64_le_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int64_le_signed" "noalloc"
+
+external extract_fastpath_int64_ne_signed : string -> int -> int64 -> int64 = "ocaml_bitstring_extract_fastpath_int64_ne_signed" "noalloc"
+
+(* 'construct' functions are used in BITSTRING constructors. *)
 val construct_bit : Buffer.t -> bool -> int -> exn -> unit
 
 val construct_char_unsigned : Buffer.t -> int -> int -> exn -> unit
 
+val construct_char_signed : Buffer.t -> int -> int -> exn -> unit
+
 val construct_int_be_unsigned : Buffer.t -> int -> int -> exn -> unit
 
+val construct_int_le_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_int_be_signed : Buffer.t -> int -> int -> exn -> unit
+
+val construct_int_le_signed : Buffer.t -> int -> int -> exn -> unit
+
+val construct_int_ne_signed : Buffer.t -> int -> int -> exn -> unit
+
+val construct_int_ee_signed : endian -> Buffer.t -> int -> int -> exn -> unit
+
 val construct_int32_be_unsigned : Buffer.t -> int32 -> int -> exn -> unit
 
+val construct_int32_le_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_le_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
@@ -924,3 +1104,7 @@ val construct_int64_ee_unsigned : endian -> Buffer.t -> int64 -> int -> exn -> u
 val construct_string : Buffer.t -> string -> unit
 
 val construct_bitstring : Buffer.t -> bitstring -> unit
+
+(* Alias of functions shadowed by Core. *)
+val char_code : char -> int
+val int32_of_int : int -> int32