This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,346 @@
type bigstring =
(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
type t = bigstring
let create size = Bigarray.(Array1.create char c_layout size)
let empty = create 0
module BA1 = Bigarray.Array1
let length t = BA1.dim t
external get : t -> int -> char = "%caml_ba_ref_1"
external set : t -> int -> char -> unit = "%caml_ba_set_1"
external unsafe_get : t -> int -> char = "%caml_ba_unsafe_ref_1"
external unsafe_set : t -> int -> char -> unit = "%caml_ba_unsafe_set_1"
external unsafe_blit : t -> src_off:int -> t -> dst_off:int -> len:int -> unit =
"bigstringaf_blit_to_bigstring" [@@noalloc]
external unsafe_blit_to_bytes : t -> src_off:int -> Bytes.t -> dst_off:int -> len:int -> unit =
"bigstringaf_blit_to_bytes" [@@noalloc]
external unsafe_blit_from_bytes : Bytes.t -> src_off:int -> t -> dst_off:int -> len:int -> unit =
"bigstringaf_blit_from_bytes" [@@noalloc]
external unsafe_blit_from_string : string -> src_off:int -> t -> dst_off:int -> len:int -> unit =
"bigstringaf_blit_from_bytes" [@@noalloc]
external unsafe_memcmp : t -> int -> t -> int -> int -> int =
"bigstringaf_memcmp_bigstring" [@@noalloc]
external unsafe_memcmp_string : t -> int -> string -> int -> int -> int =
"bigstringaf_memcmp_string" [@@noalloc]
external unsafe_memchr : t -> int -> char -> int -> int =
"bigstringaf_memchr" [@@noalloc]
let sub t ~off ~len =
BA1.sub t off len
let[@inline never] invalid_bounds op buffer_len off len =
let message =
Printf.sprintf "Bigstringaf.%s invalid range: { buffer_len: %d, off: %d, len: %d }"
op buffer_len off len
in
raise (Invalid_argument message)
;;
let[@inline never] invalid_bounds_blit op src_len src_off dst_len dst_off len =
let message =
Printf.sprintf "Bigstringaf.%s invalid range: { src_len: %d, src_off: %d, dst_len: %d, dst_off: %d, len: %d }"
op src_len src_off dst_len dst_off len
in
raise (Invalid_argument message)
;;
let[@inline never] invalid_bounds_memcmp op buf1_len buf1_off buf2_len buf2_off len =
let message =
Printf.sprintf "Bigstringaf.%s invalid range: { buf1_len: %d, buf1_off: %d, buf2_len: %d, buf2_off: %d, len: %d }"
op buf1_len buf1_off buf2_len buf2_off len
in
raise (Invalid_argument message)
;;
(* A note on bounds checking.
*
* The code should perform the following check to ensure that the blit doesn't
* run off the end of the input buffer:
*
* {[off + len <= buffer_len]}
*
* However, this may lead to an integer overflow for large values of [off],
* e.g., [max_int], which will cause the comparison to return [true] when it
* should really return [false].
*
* An equivalent comparison that does not run into this integer overflow
* problem is:
*
* {[buffer_len - off => len]}
*
* This is checking that the input buffer, less the offset, is sufficiently
* long to perform the blit. Since the expression is subtracting [off] rather
* than adding it, it doesn't suffer from the overflow that the previous
* inequality did. As long as there is a check to ensure that [off] is not
* negative, it won't underflow either. *)
let copy t ~off ~len =
let buffer_len = length t in
if len < 0 || off < 0 || buffer_len - off < len
then invalid_bounds "copy" buffer_len off len;
let dst = create len in
unsafe_blit t ~src_off:off dst ~dst_off:0 ~len;
dst
;;
let substring t ~off ~len =
let buffer_len = length t in
if len < 0 || off < 0 || buffer_len - off < len
then invalid_bounds "substring" buffer_len off len;
let b = Bytes.create len in
unsafe_blit_to_bytes t ~src_off:off b ~dst_off:0 ~len;
Bytes.unsafe_to_string b
;;
let to_string t =
let len = length t in
let b = Bytes.create len in
unsafe_blit_to_bytes t ~src_off:0 b ~dst_off:0 ~len;
Bytes.unsafe_to_string b
;;
let of_string ~off ~len s =
let buffer_len = String.length s in
if len < 0 || off < 0 || buffer_len - off < len
then invalid_bounds "of_string" buffer_len off len;
let b = create len in
unsafe_blit_from_string s ~src_off:off b ~dst_off:0 ~len;
b
;;
let blit src ~src_off dst ~dst_off ~len =
let src_len = length src in
let dst_len = length dst in
if len < 0
then invalid_bounds_blit "blit" src_len src_off dst_len dst_off len;
if src_off < 0 || src_len - src_off < len
then invalid_bounds_blit "blit" src_len src_off dst_len dst_off len;
if dst_off < 0 || dst_len - dst_off < len
then invalid_bounds_blit "blit" src_len src_off dst_len dst_off len;
unsafe_blit src ~src_off dst ~dst_off ~len
;;
let blit_from_string src ~src_off dst ~dst_off ~len =
let src_len = String.length src in
let dst_len = length dst in
if len < 0
then invalid_bounds_blit "blit_from_string" src_len src_off dst_len dst_off len;
if src_off < 0 || src_len - src_off < len
then invalid_bounds_blit "blit_from_string" src_len src_off dst_len dst_off len;
if dst_off < 0 || dst_len - dst_off < len
then invalid_bounds_blit "blit_from_string" src_len src_off dst_len dst_off len;
unsafe_blit_from_string src ~src_off dst ~dst_off ~len
;;
let blit_from_bytes src ~src_off dst ~dst_off ~len =
let src_len = Bytes.length src in
let dst_len = length dst in
if len < 0
then invalid_bounds_blit "blit_from_bytes" src_len src_off dst_len dst_off len;
if src_off < 0 || src_len - src_off < len
then invalid_bounds_blit "blit_from_bytes" src_len src_off dst_len dst_off len;
if dst_off < 0 || dst_len - dst_off < len
then invalid_bounds_blit "blit_from_bytes" src_len src_off dst_len dst_off len;
unsafe_blit_from_bytes src ~src_off dst ~dst_off ~len
;;
let blit_to_bytes src ~src_off dst ~dst_off ~len =
let src_len = length src in
let dst_len = Bytes.length dst in
if len < 0
then invalid_bounds_blit "blit_to_bytes" src_len src_off dst_len dst_off len;
if src_off < 0 || src_len - src_off < len
then invalid_bounds_blit "blit_to_bytes" src_len src_off dst_len dst_off len;
if dst_off < 0 || dst_len - dst_off < len
then invalid_bounds_blit "blit_to_bytes" src_len src_off dst_len dst_off len;
unsafe_blit_to_bytes src ~src_off dst ~dst_off ~len
;;
let memcmp buf1 buf1_off buf2 buf2_off len =
let buf1_len = length buf1 in
let buf2_len = length buf2 in
if len < 0
then invalid_bounds_memcmp "memcmp" buf1_len buf1_off buf2_len buf2_off len;
if buf1_off < 0 || buf1_len - buf1_off < len
then invalid_bounds_memcmp "memcmp" buf1_len buf1_off buf2_len buf2_off len;
if buf2_off < 0 || buf2_len - buf2_off < len
then invalid_bounds_memcmp "memcmp" buf1_len buf1_off buf2_len buf2_off len;
unsafe_memcmp buf1 buf1_off buf2 buf2_off len
;;
let memcmp_string buf1 buf1_off buf2 buf2_off len =
let buf1_len = length buf1 in
let buf2_len = String.length buf2 in
if len < 0
then invalid_bounds_memcmp "memcmp_string" buf1_len buf1_off buf2_len buf2_off len;
if buf1_off < 0 || buf1_len - buf1_off < len
then invalid_bounds_memcmp "memcmp_string" buf1_len buf1_off buf2_len buf2_off len;
if buf2_off < 0 || buf2_len - buf2_off < len
then invalid_bounds_memcmp "memcmp_string" buf1_len buf1_off buf2_len buf2_off len;
unsafe_memcmp_string buf1 buf1_off buf2 buf2_off len
;;
let memchr buf buf_off chr len =
let buf_len = length buf in
if len < 0
then invalid_bounds "memchr" buf_len buf_off len;
if buf_off < 0 || buf_len - buf_off < len
then invalid_bounds "memchr" buf_len buf_off len;
unsafe_memchr buf buf_off chr len
(* Safe operations *)
external caml_bigstring_set_16 : bigstring -> int -> int -> unit = "%caml_bigstring_set16"
external caml_bigstring_set_32 : bigstring -> int -> int32 -> unit = "%caml_bigstring_set32"
external caml_bigstring_set_64 : bigstring -> int -> int64 -> unit = "%caml_bigstring_set64"
external caml_bigstring_get_16 : bigstring -> int -> int = "%caml_bigstring_get16"
external caml_bigstring_get_32 : bigstring -> int -> int32 = "%caml_bigstring_get32"
external caml_bigstring_get_64 : bigstring -> int -> int64 = "%caml_bigstring_get64"
module Swap = struct
external bswap16 : int -> int = "%bswap16"
external bswap_int32 : int32 -> int32 = "%bswap_int32"
external bswap_int64 : int64 -> int64 = "%bswap_int64"
let caml_bigstring_set_16 bs off i =
caml_bigstring_set_16 bs off (bswap16 i)
let caml_bigstring_set_32 bs off i =
caml_bigstring_set_32 bs off (bswap_int32 i)
let caml_bigstring_set_64 bs off i =
caml_bigstring_set_64 bs off (bswap_int64 i)
let caml_bigstring_get_16 bs off =
bswap16 (caml_bigstring_get_16 bs off)
let caml_bigstring_get_32 bs off =
bswap_int32 (caml_bigstring_get_32 bs off)
let caml_bigstring_get_64 bs off =
bswap_int64 (caml_bigstring_get_64 bs off)
let get_int16_sign_extended x off =
((caml_bigstring_get_16 x off) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16)
end
let set_int16_le, set_int16_be =
if Sys.big_endian
then Swap.caml_bigstring_set_16, caml_bigstring_set_16
else caml_bigstring_set_16 , Swap.caml_bigstring_set_16
let set_int32_le, set_int32_be =
if Sys.big_endian
then Swap.caml_bigstring_set_32, caml_bigstring_set_32
else caml_bigstring_set_32 , Swap.caml_bigstring_set_32
let set_int64_le, set_int64_be =
if Sys.big_endian
then Swap.caml_bigstring_set_64, caml_bigstring_set_64
else caml_bigstring_set_64 , Swap.caml_bigstring_set_64
let get_int16_le, get_int16_be =
if Sys.big_endian
then Swap.caml_bigstring_get_16, caml_bigstring_get_16
else caml_bigstring_get_16 , Swap.caml_bigstring_get_16
let get_int16_sign_extended_noswap x off =
((caml_bigstring_get_16 x off) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16)
let get_int16_sign_extended_le, get_int16_sign_extended_be =
if Sys.big_endian
then Swap.get_int16_sign_extended , get_int16_sign_extended_noswap
else get_int16_sign_extended_noswap, Swap.get_int16_sign_extended
let get_int32_le, get_int32_be =
if Sys.big_endian
then Swap.caml_bigstring_get_32, caml_bigstring_get_32
else caml_bigstring_get_32 , Swap.caml_bigstring_get_32
let get_int64_le, get_int64_be =
if Sys.big_endian
then Swap.caml_bigstring_get_64, caml_bigstring_get_64
else caml_bigstring_get_64 , Swap.caml_bigstring_get_64
(* Unsafe operations *)
external caml_bigstring_unsafe_set_16 : bigstring -> int -> int -> unit = "%caml_bigstring_set16u"
external caml_bigstring_unsafe_set_32 : bigstring -> int -> int32 -> unit = "%caml_bigstring_set32u"
external caml_bigstring_unsafe_set_64 : bigstring -> int -> int64 -> unit = "%caml_bigstring_set64u"
external caml_bigstring_unsafe_get_16 : bigstring -> int -> int = "%caml_bigstring_get16u"
external caml_bigstring_unsafe_get_32 : bigstring -> int -> int32 = "%caml_bigstring_get32u"
external caml_bigstring_unsafe_get_64 : bigstring -> int -> int64 = "%caml_bigstring_get64u"
module USwap = struct
external bswap16 : int -> int = "%bswap16"
external bswap_int32 : int32 -> int32 = "%bswap_int32"
external bswap_int64 : int64 -> int64 = "%bswap_int64"
let caml_bigstring_unsafe_set_16 bs off i =
caml_bigstring_unsafe_set_16 bs off (bswap16 i)
let caml_bigstring_unsafe_set_32 bs off i =
caml_bigstring_unsafe_set_32 bs off (bswap_int32 i)
let caml_bigstring_unsafe_set_64 bs off i =
caml_bigstring_unsafe_set_64 bs off (bswap_int64 i)
let caml_bigstring_unsafe_get_16 bs off =
bswap16 (caml_bigstring_unsafe_get_16 bs off)
let caml_bigstring_unsafe_get_32 bs off =
bswap_int32 (caml_bigstring_unsafe_get_32 bs off)
let caml_bigstring_unsafe_get_64 bs off =
bswap_int64 (caml_bigstring_unsafe_get_64 bs off)
end
let unsafe_set_int16_le, unsafe_set_int16_be =
if Sys.big_endian
then USwap.caml_bigstring_unsafe_set_16, caml_bigstring_unsafe_set_16
else caml_bigstring_unsafe_set_16 , USwap.caml_bigstring_unsafe_set_16
let unsafe_set_int32_le, unsafe_set_int32_be =
if Sys.big_endian
then USwap.caml_bigstring_unsafe_set_32, caml_bigstring_unsafe_set_32
else caml_bigstring_unsafe_set_32 , USwap.caml_bigstring_unsafe_set_32
let unsafe_set_int64_le, unsafe_set_int64_be =
if Sys.big_endian
then USwap.caml_bigstring_unsafe_set_64, caml_bigstring_unsafe_set_64
else caml_bigstring_unsafe_set_64 , USwap.caml_bigstring_unsafe_set_64
let unsafe_get_int16_le, unsafe_get_int16_be =
if Sys.big_endian
then USwap.caml_bigstring_unsafe_get_16, caml_bigstring_unsafe_get_16
else caml_bigstring_unsafe_get_16 , USwap.caml_bigstring_unsafe_get_16
let unsafe_get_int16_sign_extended_le x off =
((unsafe_get_int16_le x off) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16)
let unsafe_get_int16_sign_extended_be x off =
((unsafe_get_int16_be x off ) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16)
let unsafe_get_int32_le, unsafe_get_int32_be =
if Sys.big_endian
then USwap.caml_bigstring_unsafe_get_32, caml_bigstring_unsafe_get_32
else caml_bigstring_unsafe_get_32 , USwap.caml_bigstring_unsafe_get_32
let unsafe_get_int64_le, unsafe_get_int64_be =
if Sys.big_endian
then USwap.caml_bigstring_unsafe_get_64, caml_bigstring_unsafe_get_64
else caml_bigstring_unsafe_get_64 , USwap.caml_bigstring_unsafe_get_64