let bitstring_of_file fname =
let chan = open_in_bin fname in
- let bs = bitstring_of_chan chan in
- close_in chan;
- bs
+ try
+ let bs = bitstring_of_chan chan in
+ close_in chan;
+ bs
+ with exn ->
+ close_in chan;
+ raise exn
let bitstring_length (_, _, len) = len
str.[i] <- Char.chr c;
loop data off len (i+1)
) else if len > 0 then (
+ (* XXX Is this correct? It should write into the high bits
+ * of the last byte.
+ *)
let c, off, len = extract_char_unsigned data off len len in
str.[i] <- Char.chr c
)
str
)
+(* To channel. *)
+
+let bitstring_to_chan ((data, off, len) as bits) chan =
+ (* Fail if the bitstring length isn't a multiple of 8. *)
+ if len land 7 <> 0 then invalid_arg "bitstring_to_chan";
+
+ if off land 7 = 0 then
+ (* Easy case: string is byte-aligned. *)
+ output chan data (off lsr 3) (len lsr 3)
+ else (
+ (* Bit-twiddling case: reuse string_of_bitstring *)
+ let str = string_of_bitstring bits in
+ output_string chan str
+ )
+
+let bitstring_to_file bits filename =
+ let chan = open_out_bin filename in
+ try
+ bitstring_to_chan bits chan;
+ close_out chan
+ with exn ->
+ close_out chan;
+ raise exn
+
(*----------------------------------------------------------------------*)
(* Display functions. *)
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} *)