From 9e69d8854390b6804b3604e33d4d602c31666391 Mon Sep 17 00:00:00 2001 From: Anurag Soni Date: Tue, 4 May 2021 20:03:50 -0400 Subject: [PATCH 1/4] add binding to the c memchr function. --- lib/bigstringaf.ml | 10 ++++++++++ lib/bigstringaf.mli | 12 ++++++++++++ lib/bigstringaf_stubs.c | 19 +++++++++++++++++++ lib_test/s.ml | 4 ++++ lib_test/test_bigstringaf.ml | 21 +++++++++++++++++++++ 5 files changed, 66 insertions(+) diff --git a/lib/bigstringaf.ml b/lib/bigstringaf.ml index ed0fe0b..5361fae 100644 --- a/lib/bigstringaf.ml +++ b/lib/bigstringaf.ml @@ -34,6 +34,9 @@ external unsafe_memcmp : t -> int -> t -> int -> int -> int = 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 @@ -189,6 +192,13 @@ let memcmp_string buf1 buf1_off buf2 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 *) diff --git a/lib/bigstringaf.mli b/lib/bigstringaf.mli index 92866db..d4b12d4 100644 --- a/lib/bigstringaf.mli +++ b/lib/bigstringaf.mli @@ -164,6 +164,12 @@ val blit_to_bytes : t -> src_off:int -> Bytes.t -> dst_off:int -> len:int -> uni val memcmp : t -> int -> t -> int -> int -> int val memcmp_string : t -> int -> string -> int -> int -> int +(** {4 [memchr]} + + Search for a byte in a bigstring using [memcmp]. Similar to [unsafe_memchr] + but this performs bounds checks. + *) +val memchr : t -> int -> char -> int -> int (** {2 Memory-unsafe Operations} @@ -267,3 +273,9 @@ val unsafe_blit_to_bytes : t -> src_off:int -> Bytes.t -> dst_off:int -> len:int val unsafe_memcmp : t -> int -> t -> int -> int -> int val unsafe_memcmp_string : t -> int -> string -> int -> int -> int + +(** {4 [memchr]} + + Search for a byte in a bigstring using [memcmp]. + *) +val unsafe_memchr : t -> int -> char -> int -> int diff --git a/lib/bigstringaf_stubs.c b/lib/bigstringaf_stubs.c index 1c02abf..915d47d 100644 --- a/lib/bigstringaf_stubs.c +++ b/lib/bigstringaf_stubs.c @@ -83,3 +83,22 @@ bigstringaf_memcmp_string(value vba, value vba_off, value vstr, value vstr_off, int result = memcmp(buf1, buf2, len); return Val_int(result); } + +CAMLprim value +bigstringaf_memchr(value vba, value vba_off, value vchr, value vlen) +{ + size_t off = Unsigned_long_val(vba_off); + char *buf = ((char *)Caml_ba_data_val(vba)) + off; + size_t len = Unsigned_long_val(vlen); + int c = Int_val(vchr); + + char* res = memchr(buf, c, len); + if (res == NULL) + { + return Val_long(-1); + } + else + { + return Val_long(off + res - buf); + } +} diff --git a/lib_test/s.ml b/lib_test/s.ml index 7b14847..d7b6602 100644 --- a/lib_test/s.ml +++ b/lib_test/s.ml @@ -36,3 +36,7 @@ module type Memcmp = sig val memcmp : Bigstringaf.t -> int -> Bigstringaf.t -> int -> int -> int val memcmp_string : Bigstringaf.t -> int -> String.t -> int -> int -> int end + +module type Memchr = sig + val memchr : Bigstringaf.t -> int -> char -> int -> int +end diff --git a/lib_test/test_bigstringaf.ml b/lib_test/test_bigstringaf.ml index 9cea214..e78e998 100644 --- a/lib_test/test_bigstringaf.ml +++ b/lib_test/test_bigstringaf.ml @@ -233,6 +233,19 @@ let memcmp_string m () = () ;; +let memchr m () = + let module Memchr = (val m : S.Memchr) in + let open Memchr in + let string = "hello world foo bar baz" in + let buffer = Bigstringaf.of_string ~off:0 ~len:(String.length string) string in + let buffer_len = Bigstringaf.length buffer in + Alcotest.(check int) "memchr starting at offset 0" (String.index_from string 0 ' ') + (memchr buffer 0 ' ' buffer_len); + Alcotest.(check int) "memchr with an offset" (String.index_from string 7 ' ') + (memchr buffer 7 ' ' (buffer_len - 7)); + Alcotest.(check int) "memchr char not found" (-1) + (memchr buffer 0 'Z' buffer_len) + let negative_bounds_check () = let open Bigstringaf in let buf = Bigstringaf.empty in @@ -293,6 +306,7 @@ let safe_operations = let module Setters : S.Setters = Bigstringaf in let module Blit : S.Blit = Bigstringaf in let module Memcmp : S.Memcmp = Bigstringaf in + let module Memchr : S.Memchr = Bigstringaf in [ "index out of bounds", `Quick, index_out_of_bounds ; "getters" , `Quick, getters (module Getters) ; "setters" , `Quick, setters (module Setters) @@ -302,6 +316,7 @@ let safe_operations = ; "memcmp" , `Quick, memcmp (module Memcmp) ; "memcmp_string" , `Quick, memcmp_string (module Memcmp) ; "negative length" , `Quick, negative_bounds_check + ; "memchr" , `Quick, memchr (module Memchr) ] let unsafe_operations = @@ -348,6 +363,11 @@ let unsafe_operations = let memcmp = unsafe_memcmp let memcmp_string = unsafe_memcmp_string end in + let module Memchr : S.Memchr = struct + open Bigstringaf + + let memchr = unsafe_memchr + end in [ "getters" , `Quick, getters (module Getters) ; "setters" , `Quick, setters (module Setters) ; "blit" , `Quick, blit (module Blit) @@ -355,6 +375,7 @@ let unsafe_operations = ; "blit_from_bytes", `Quick, blit_from_bytes (module Blit) ; "memcmp" , `Quick, memcmp (module Memcmp) ; "memcmp_string" , `Quick, memcmp_string (module Memcmp) + ; "memchr" , `Quick, memchr (module Memchr) ] let () = From db125fe72caf3fca5970e088cd3d3ead15f1e7ee Mon Sep 17 00:00:00 2001 From: Anurag Soni Date: Tue, 4 May 2021 20:10:11 -0400 Subject: [PATCH 2/4] add javascript stub --- lib/runtime.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/runtime.js b/lib/runtime.js index 102f054..276d9e4 100644 --- a/lib/runtime.js +++ b/lib/runtime.js @@ -68,3 +68,14 @@ function bigstringaf_memcmp_string(ba, ba_off, str, str_off, len) { } return 0; } + +//Provides: bigstringaf_memchr +//Requires: caml_ba_get_1 +function bigstringaf_memchr(ba, ba_off, chr, len) { + for (var i = 0; i < len; i++) { + if (caml_ba_get_1(ba, ba_off + i) == chr) { + return (ba_off + i); + } + } + return -1; +} From fc9a19d70491693e087947ff2222f231e34b526a Mon Sep 17 00:00:00 2001 From: Anurag Soni Date: Sat, 26 Jun 2021 11:52:53 -0400 Subject: [PATCH 3/4] fix docstring --- lib/bigstringaf.mli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bigstringaf.mli b/lib/bigstringaf.mli index d4b12d4..7f6c34b 100644 --- a/lib/bigstringaf.mli +++ b/lib/bigstringaf.mli @@ -166,7 +166,7 @@ val memcmp_string : t -> int -> string -> int -> int -> int (** {4 [memchr]} - Search for a byte in a bigstring using [memcmp]. Similar to [unsafe_memchr] + Search for a byte in a bigstring using [memchr]. Similar to [unsafe_memchr] but this performs bounds checks. *) val memchr : t -> int -> char -> int -> int @@ -276,6 +276,6 @@ val unsafe_memcmp_string : t -> int -> string -> int -> int -> int (** {4 [memchr]} - Search for a byte in a bigstring using [memcmp]. + Search for a byte in a bigstring using [memchr]. *) val unsafe_memchr : t -> int -> char -> int -> int From fabb5d7965c957715120747b693fdd6cab1f1de5 Mon Sep 17 00:00:00 2001 From: Spiros Eliopoulos Date: Mon, 5 Jul 2021 16:30:04 -0400 Subject: [PATCH 4/4] pr47: update documentation --- lib/bigstringaf.mli | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/bigstringaf.mli b/lib/bigstringaf.mli index 7f6c34b..bbf02a8 100644 --- a/lib/bigstringaf.mli +++ b/lib/bigstringaf.mli @@ -164,11 +164,11 @@ val blit_to_bytes : t -> src_off:int -> Bytes.t -> dst_off:int -> len:int -> uni val memcmp : t -> int -> t -> int -> int -> int val memcmp_string : t -> int -> string -> int -> int -> int -(** {4 [memchr]} +(** {3 [memchr]} + + Search for a byte using [memchr], returning [-1] if the byte is not found. + Performing bounds checking before the C call. *) - Search for a byte in a bigstring using [memchr]. Similar to [unsafe_memchr] - but this performs bounds checks. - *) val memchr : t -> int -> char -> int -> int (** {2 Memory-unsafe Operations} @@ -274,8 +274,9 @@ val unsafe_blit_to_bytes : t -> src_off:int -> Bytes.t -> dst_off:int -> len:int val unsafe_memcmp : t -> int -> t -> int -> int -> int val unsafe_memcmp_string : t -> int -> string -> int -> int -> int -(** {4 [memchr]} +(** {3 [memchr]} + + Search for a byte using [memchr], returning [-1] if the byte is not found. + It does not check bounds before the C call. *) - Search for a byte in a bigstring using [memchr]. - *) val unsafe_memchr : t -> int -> char -> int -> int