common/mlstdutils: Implement ‘Char.mem’, ‘String.span’ and ‘String.cspan’.

Char.mem tells you if a byte is a member of a string.

String.span and String.cspan are like the C functions strspn and
strcspn.
This commit is contained in:
Richard W.M. Jones
2017-06-15 15:29:35 +01:00
parent b31a076717
commit add53125a4
3 changed files with 56 additions and 0 deletions

View File

@@ -74,6 +74,8 @@ module Char = struct
| 'e' | 'E' -> 14
| 'f' | 'F' -> 15
| _ -> -1
let mem c str = String.contains str c
end
module String = struct
@@ -246,6 +248,24 @@ module String = struct
List.map f (explode str)
let spaces n = String.make n ' '
let span str accept =
let len = String.length str in
let rec loop i =
if i >= len then len
else if Char.mem (String.unsafe_get str i) accept then loop (i+1)
else i
in
loop 0
let cspan str reject =
let len = String.length str in
let rec loop i =
if i >= len then len
else if Char.mem (String.unsafe_get str i) reject then i
else loop (i+1)
in
loop 0
end
let (//) = Filename.concat

View File

@@ -41,6 +41,12 @@ module Char : sig
val hexdigit : char -> int
(** Return the value of a hex digit. If the char is not in
the set [[0-9a-fA-F]] then this returns [-1]. *)
val mem : char -> string -> bool
(** [mem c str] returns true if the byte [c] is contained in [str].
This is actually the same as {!String.contains} with the
parameters reversed. *)
end
(** Override the Char module from stdlib. *)
@@ -109,6 +115,15 @@ module String : sig
(** Explode string, then map function over the characters. *)
val spaces : int -> string
(** [spaces n] creates a string of n spaces. *)
val span : string -> string -> int
val cspan : string -> string -> int
(** [span str accept] returns the length in bytes of the initial
segment of [str] which contains only bytes in [accept].
[cspan str reject] returns the length in bytes of the initial
segment of [str] which contains only bytes {!i not} in [reject].
These work exactly like the C functions [strspn] and [strcspn]. *)
end
(** Override the String module from stdlib. *)

View File

@@ -50,6 +50,14 @@ and test_swap int_of_x x_of_int i s =
assert_equal_int64 i (int_of_x s);
assert_equal_string s (x_of_int i)
(* Test Std_utils.Char.mem. *)
let test_char_mem ctx =
assert_bool "Char.mem" (Char.mem 'a' "abc");
assert_bool "Char.mem" (Char.mem 'b' "abc");
assert_bool "Char.mem" (Char.mem 'c' "abc");
assert_bool "Char.mem" (not (Char.mem 'd' "abc"));
assert_bool "Char.mem" (not (Char.mem 'a' ""))
(* Test Std_utils.String.is_prefix. *)
let test_string_is_prefix ctx =
assert_bool "String.is_prefix,," (String.is_prefix "" "");
@@ -91,16 +99,29 @@ let test_string_lines_split ctx =
assert_equal_stringlist ["A\nB"; ""] (String.lines_split "A\\\nB\n");
assert_equal_stringlist ["A\nB\n"] (String.lines_split "A\\\nB\\\n")
(* Test Std_utils.String.span and cspan. *)
let test_string_span ctx =
assert_equal_int 3 (String.span "aaabb" "a");
assert_equal_int 3 (String.span "aaaba" "a");
assert_equal_int 3 (String.span "aba" "ab");
assert_equal_int 0 (String.span "" "ab");
assert_equal_int 3 (String.cspan "defab" "ab");
assert_equal_int 3 (String.cspan "defba" "ab");
assert_equal_int 3 (String.cspan "def" "ab");
assert_equal_int 0 (String.cspan "" "ab")
(* Suites declaration. *)
let suite =
"mllib Std_utils" >:::
[
"subdirectory" >:: test_subdirectory;
"numeric.byteswap" >:: test_byteswap;
"char.mem" >:: test_char_mem;
"strings.is_prefix" >:: test_string_is_prefix;
"strings.is_suffix" >:: test_string_is_suffix;
"strings.find" >:: test_string_find;
"strings.lines_split" >:: test_string_lines_split;
"strings.span" >:: test_string_span;
]
let () =