+ (* Optimize the common (byte-aligned) case. *)
+ if off land 7 = 0 then (
+ let byte = Char.code data.[byteoff] in
+ byte lsr (8 - flen), off+flen, len-flen
+ ) else (
+ (* Extract the 16 bits at byteoff and byteoff+1 (note that the
+ * second byte might not exist in the original string).
+ *)
+ let strlen = String.length data in
+
+ let word =
+ (_get_byte data byteoff strlen lsl 8) +
+ _get_byte data (byteoff+1) strlen in
+
+ (* Mask off the top bits. *)
+ let bitmask = (1 lsl (16 - (off land 7))) - 1 in
+ let word = word land bitmask in
+ (* Shift right to get rid of the bottom bits. *)
+ let shift = 16 - ((off land 7) + flen) in
+ let word = word lsr shift in
+
+ word, off+flen, len-flen
+ )
+
+(* Extract [9..31] bits. We have to consider endianness and signedness. *)
+let extract_int_be_unsigned data off len flen =
+ let byteoff = off lsr 3 in
+
+ let strlen = String.length data in
+
+ let word =
+ (* Optimize the common (byte-aligned) case. *)
+ if off land 7 = 0 then (
+ let word =
+ (_get_byte data byteoff strlen lsl 23) +
+ (_get_byte data (byteoff+1) strlen lsl 15) +
+ (_get_byte data (byteoff+2) strlen lsl 7) +
+ (_get_byte data (byteoff+3) strlen lsr 1) in
+ word lsr (31 - flen)
+ ) else if flen <= 24 then (
+ (* Extract the 31 bits at byteoff .. byteoff+3. *)
+ let word =
+ (_get_byte data byteoff strlen lsl 23) +
+ (_get_byte data (byteoff+1) strlen lsl 15) +
+ (_get_byte data (byteoff+2) strlen lsl 7) +
+ (_get_byte data (byteoff+3) strlen lsr 1) in
+ (* Mask off the top bits. *)
+ let bitmask = (1 lsl (31 - (off land 7))) - 1 in
+ let word = word land bitmask in
+ (* Shift right to get rid of the bottom bits. *)
+ let shift = 31 - ((off land 7) + flen) in
+ word lsr shift
+ ) else (
+ (* Extract the next 31 bits, slow method. *)
+ let word =
+ let c0, off, len = extract_char_unsigned data off len 8 in
+ let c1, off, len = extract_char_unsigned data off len 8 in
+ let c2, off, len = extract_char_unsigned data off len 8 in
+ let c3, off, len = extract_char_unsigned data off len 7 in
+ (c0 lsl 23) + (c1 lsl 15) + (c2 lsl 7) + c3 in
+ word lsr (31 - flen)
+ ) in
+ word, off+flen, len-flen
+
+let extract_int_le_unsigned data off len flen =
+ let v, off, len = extract_int_be_unsigned data off len flen in
+ let v = I.byteswap v flen in
+ v, off, len
+
+let _make_int32_be c0 c1 c2 c3 =
+ Int32.logor
+ (Int32.logor
+ (Int32.logor
+ (Int32.shift_left c0 24)
+ (Int32.shift_left c1 16))
+ (Int32.shift_left c2 8))
+ c3
+
+let _make_int32_le c0 c1 c2 c3 =
+ Int32.logor
+ (Int32.logor
+ (Int32.logor
+ (Int32.shift_left c3 24)
+ (Int32.shift_left c2 16))
+ (Int32.shift_left c1 8))
+ c0
+
+(* Extract exactly 32 bits. We have to consider endianness and signedness. *)
+let extract_int32_be_unsigned data off len flen =
+ let byteoff = off lsr 3 in
+
+ let strlen = String.length data in
+
+ let word =
+ (* Optimize the common (byte-aligned) case. *)
+ if off land 7 = 0 then (
+ let word =
+ let c0 = _get_byte32 data byteoff strlen in
+ let c1 = _get_byte32 data (byteoff+1) strlen in
+ let c2 = _get_byte32 data (byteoff+2) strlen in
+ let c3 = _get_byte32 data (byteoff+3) strlen in
+ _make_int32_be c0 c1 c2 c3 in
+ Int32.shift_right_logical word (32 - flen)
+ ) else (
+ (* Extract the next 32 bits, slow method. *)
+ let word =
+ let c0, off, len = extract_char_unsigned data off len 8 in
+ let c1, off, len = extract_char_unsigned data off len 8 in
+ let c2, off, len = extract_char_unsigned data off len 8 in
+ let c3, _, _ = extract_char_unsigned data off len 8 in
+ let c0 = Int32.of_int c0 in
+ let c1 = Int32.of_int c1 in
+ let c2 = Int32.of_int c2 in
+ let c3 = Int32.of_int c3 in
+ _make_int32_be c0 c1 c2 c3 in
+ Int32.shift_right_logical word (32 - flen)
+ ) in
+ word, off+flen, len-flen
+
+let extract_int32_le_unsigned data off len flen =
+ let v, off, len = extract_int32_be_unsigned data off len flen in
+ let v = I32.byteswap v flen in
+ v, off, len
+
+let _make_int64_be c0 c1 c2 c3 c4 c5 c6 c7 =
+ Int64.logor
+ (Int64.logor
+ (Int64.logor
+ (Int64.logor
+ (Int64.logor
+ (Int64.logor
+ (Int64.logor
+ (Int64.shift_left c0 56)
+ (Int64.shift_left c1 48))
+ (Int64.shift_left c2 40))
+ (Int64.shift_left c3 32))
+ (Int64.shift_left c4 24))
+ (Int64.shift_left c5 16))
+ (Int64.shift_left c6 8))
+ c7
+
+let _make_int64_le c0 c1 c2 c3 c4 c5 c6 c7 =
+ _make_int64_be c7 c6 c5 c4 c3 c2 c1 c0
+
+(* Extract [1..64] bits. We have to consider endianness and signedness. *)
+let extract_int64_be_unsigned data off len flen =
+ let byteoff = off lsr 3 in
+
+ let strlen = String.length data in
+