+
+ (* Check a value is in range 0 .. 2^bits-1. *)
+ let range_unsigned v bits =
+ let mask = lnot (mask bits) in
+ (v land mask) = zero
+
+ (* Call function g on the top bits, then f on each full byte
+ * (big endian - so start at top).
+ *)
+ let rec map_bytes_be g f v bits =
+ if bits >= 8 then (
+ map_bytes_be g f (v >> 8) (bits-8);
+ let lsb = v land ff in
+ f (to_int lsb)
+ ) else if bits > 0 then (
+ let lsb = v land (mask bits) in
+ g (to_int lsb) bits
+ )
+end
+
+module I64 = struct
+ (* Bitwise operations on int64s. Note we try to keep it as similar
+ * as possible to the I/I32 modules above, to make it easier to track
+ * down bugs.
+ *)
+ let (<<) = Int64.shift_left
+ let (>>) = Int64.shift_right_logical
+ let (land) = Int64.logand
+ let (lor) = Int64.logor
+ let lnot = Int64.lognot
+ let pred = Int64.pred
+ let max_int = Int64.max_int
+ let to_int = Int64.to_int
+ let zero = Int64.zero
+ let one = Int64.one
+ let minus_one = Int64.minus_one
+ let ff = 0xff_L
+
+ (* Create a mask so many bits wide. *)
+ let mask bits =
+ if bits < 63 then
+ pred (one << bits)
+ else if bits = 63 then
+ max_int
+ else if bits = 64 then
+ minus_one
+ else
+ invalid_arg "Bitmatch.I64.mask"
+
+ (* Byte swap an int of a given size. *)
+ (* let byteswap v bits = *)
+
+ (* Check a value is in range 0 .. 2^bits-1. *)
+ let range_unsigned v bits =
+ let mask = lnot (mask bits) in
+ (v land mask) = zero
+
+ (* Call function g on the top bits, then f on each full byte
+ * (big endian - so start at top).
+ *)
+ let rec map_bytes_be g f v bits =
+ if bits >= 8 then (
+ map_bytes_be g f (v >> 8) (bits-8);
+ let lsb = v land ff in
+ f (to_int lsb)
+ ) else if bits > 0 then (
+ let lsb = v land (mask bits) in
+ g (to_int lsb) bits
+ )