add CCString.{to_hex,of_hex}

This commit is contained in:
Simon Cruanes 2022-04-06 10:53:26 -04:00
parent a753b0df3e
commit 34f76e926c
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
3 changed files with 69 additions and 0 deletions

View file

@ -1134,6 +1134,49 @@ let equal_caseless s1 s2: bool =
Q.(printable_string) (fun s -> equal_caseless (uppercase_ascii s) s) Q.(printable_string) (fun s -> equal_caseless (uppercase_ascii s) s)
*) *)
let to_hex (s:string) : string =
let i_to_hex (i:int) =
if i < 10 then Char.chr (i + Char.code '0')
else Char.chr (i - 10 + Char.code 'a')
in
let res = Bytes.create (2 * length s) in
for i = 0 to length s-1 do
let n = Char.code (get s i) in
Bytes.set res (2 * i) (i_to_hex ((n land 0xf0) lsr 4));
Bytes.set res (2 * i + 1) (i_to_hex (n land 0x0f));
done;
Bytes.unsafe_to_string res
let of_hex_exn (s:string) : string =
let n_of_c = function
| '0' .. '9' as c -> Char.code c - Char.code '0'
| 'a' .. 'f' as c -> 10 + Char.code c - Char.code 'a'
| _ -> invalid_arg "string: invalid hex"
in
if (String.length s mod 2 <> 0) then invalid_arg "string: hex sequence must be of even length";
let res = Bytes.make (String.length s / 2) '\x00' in
for i=0 to String.length s/2-1 do
let n1 = n_of_c (String.get s (2*i)) in
let n2 = n_of_c (String.get s (2*i+1)) in
let n = (n1 lsl 4) lor n2 in
Bytes.set res i (Char.chr n)
done;
Bytes.unsafe_to_string res
let of_hex s = try Some (of_hex_exn s) with Invalid_argument _ -> None
(*$= & ~printer:(Printf.sprintf "%S")
"0068656c6c6f20776f726c64" (to_hex "\000hello world")
"" (to_hex "")
"\000hello world" (of_hex_exn "0068656c6c6f20776f726c64")
*)
(*$Q
Q.(string) (fun s -> \
of_hex_exn (to_hex s) = s)
*)
let pp_buf buf s = let pp_buf buf s =
Buffer.add_char buf '"'; Buffer.add_char buf '"';
Buffer.add_string buf s; Buffer.add_string buf s;

View file

@ -325,6 +325,19 @@ val equal_caseless : string -> string -> bool
(** [equal_caseless s1 s2] compares [s1] and [s2] without respect to {b ascii} lowercase. (** [equal_caseless s1 s2] compares [s1] and [s2] without respect to {b ascii} lowercase.
@since 1.2 *) @since 1.2 *)
val to_hex : string -> string
(** Convert a string with arbitrary content into a hexadecimal string.
@since NEXT_RELEASE *)
val of_hex : string -> string option
(** Convert a string in hex into a string with arbitrary content.
@since NEXT_RELEASE *)
val of_hex_exn : string -> string
(** Same as {!of_hex} but fails harder.
@raise Invalid_argument if the input is not valid hex.
@since NEXT_RELEASE *)
(** {2 Finding} (** {2 Finding}
A relatively efficient algorithm for finding sub-strings. A relatively efficient algorithm for finding sub-strings.

View file

@ -354,6 +354,19 @@ val equal_caseless : string -> string -> bool
(** [equal_caseless s1 s2] compares [s1] and [s2] without respect to {b ascii} lowercase. (** [equal_caseless s1 s2] compares [s1] and [s2] without respect to {b ascii} lowercase.
@since 1.2 *) @since 1.2 *)
val to_hex : string -> string
(** Convert a string with arbitrary content into a hexadecimal string.
@since NEXT_RELEASE *)
val of_hex : string -> string option
(** Convert a string in hex into a string with arbitrary content.
@since NEXT_RELEASE *)
val of_hex_exn : string -> string
(** Same as {!of_hex} but fails harder.
@raise Invalid_argument if the input is not valid hex.
@since NEXT_RELEASE *)
(** {2 Finding} (** {2 Finding}
A relatively efficient algorithm for finding sub-strings. A relatively efficient algorithm for finding sub-strings.