This implements all of:
val int_of_le16 : string -> int64
val le16_of_int : int64 -> string
val int_of_be16 : string -> int64
val be16_of_int : int64 -> string
val int_of_le32 : string -> int64
val le32_of_int : int64 -> string
val int_of_be32 : string -> int64
val be32_of_int : int64 -> string
val int_of_le64 : string -> int64
val le64_of_int : int64 -> string
val int_of_be64 : string -> int64
val be64_of_int : int64 -> string
and tests.
---
common/mlstdutils/std_utils.ml | 131 +++++++++++++++++++++++++++++++++++
common/mlstdutils/std_utils.mli | 23 +++++-
common/mlstdutils/std_utils_tests.ml | 22 ++++--
3 files changed, 169 insertions(+), 7 deletions(-)
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index b91785a9c..363b761ce 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -272,6 +272,21 @@ external identity : 'a -> 'a = "%identity"
let roundup64 i a = let a = a -^ 1L in (i +^ a) &^ (~^ a)
let div_roundup64 i a = (i +^ a -^ 1L) /^ a
+let int_of_le16 str =
+ assert (String.length str = 2);
+ let c0 = Char.code (String.unsafe_get str 0) in
+ let c1 = Char.code (String.unsafe_get str 1) in
+ Int64.of_int c0 +^
+ (Int64.shift_left (Int64.of_int c1) 8)
+
+let le16_of_int i =
+ let c0 = i &^ 0xffL in
+ let c1 = Int64.shift_right (i &^ 0xff00L) 8 in
+ let b = Bytes.create 2 in
+ Bytes.unsafe_set b 0 (Char.unsafe_chr (Int64.to_int c0));
+ Bytes.unsafe_set b 1 (Char.unsafe_chr (Int64.to_int c1));
+ Bytes.to_string b
+
let int_of_le32 str =
assert (String.length str = 4);
let c0 = Char.code (String.unsafe_get str 0) in
@@ -295,6 +310,122 @@ let le32_of_int i =
Bytes.unsafe_set b 3 (Char.unsafe_chr (Int64.to_int c3));
Bytes.to_string b
+let int_of_le64 str =
+ assert (String.length str = 8);
+ let c0 = Char.code (String.unsafe_get str 0) in
+ let c1 = Char.code (String.unsafe_get str 1) in
+ let c2 = Char.code (String.unsafe_get str 2) in
+ let c3 = Char.code (String.unsafe_get str 3) in
+ let c4 = Char.code (String.unsafe_get str 4) in
+ let c5 = Char.code (String.unsafe_get str 5) in
+ let c6 = Char.code (String.unsafe_get str 6) in
+ let c7 = Char.code (String.unsafe_get str 7) in
+ Int64.of_int c0 +^
+ (Int64.shift_left (Int64.of_int c1) 8) +^
+ (Int64.shift_left (Int64.of_int c2) 16) +^
+ (Int64.shift_left (Int64.of_int c3) 24) +^
+ (Int64.shift_left (Int64.of_int c4) 32) +^
+ (Int64.shift_left (Int64.of_int c5) 40) +^
+ (Int64.shift_left (Int64.of_int c6) 48) +^
+ (Int64.shift_left (Int64.of_int c7) 56)
+
+let le64_of_int i =
+ let c0 = i &^ 0xffL in
+ let c1 = Int64.shift_right (i &^ 0xff00L) 8 in
+ let c2 = Int64.shift_right (i &^ 0xff0000L) 16 in
+ let c3 = Int64.shift_right (i &^ 0xff000000L) 24 in
+ let c4 = Int64.shift_right (i &^ 0xff00000000L) 32 in
+ let c5 = Int64.shift_right (i &^ 0xff0000000000L) 40 in
+ let c6 = Int64.shift_right (i &^ 0xff000000000000L) 48 in
+ let c7 = Int64.shift_right (i &^ 0xff00000000000000L) 56 in
+ let b = Bytes.create 8 in
+ Bytes.unsafe_set b 0 (Char.unsafe_chr (Int64.to_int c0));
+ Bytes.unsafe_set b 1 (Char.unsafe_chr (Int64.to_int c1));
+ Bytes.unsafe_set b 2 (Char.unsafe_chr (Int64.to_int c2));
+ Bytes.unsafe_set b 3 (Char.unsafe_chr (Int64.to_int c3));
+ Bytes.unsafe_set b 4 (Char.unsafe_chr (Int64.to_int c4));
+ Bytes.unsafe_set b 5 (Char.unsafe_chr (Int64.to_int c5));
+ Bytes.unsafe_set b 6 (Char.unsafe_chr (Int64.to_int c6));
+ Bytes.unsafe_set b 7 (Char.unsafe_chr (Int64.to_int c7));
+ Bytes.to_string b
+
+let int_of_be16 str =
+ assert (String.length str = 2);
+ let c0 = Char.code (String.unsafe_get str 0) in
+ let c1 = Char.code (String.unsafe_get str 1) in
+ Int64.of_int c1 +^
+ (Int64.shift_left (Int64.of_int c0) 8)
+
+let be16_of_int i =
+ let c0 = i &^ 0xffL in
+ let c1 = Int64.shift_right (i &^ 0xff00L) 8 in
+ let b = Bytes.create 2 in
+ Bytes.unsafe_set b 0 (Char.unsafe_chr (Int64.to_int c1));
+ Bytes.unsafe_set b 1 (Char.unsafe_chr (Int64.to_int c0));
+ Bytes.to_string b
+
+let int_of_be32 str =
+ assert (String.length str = 4);
+ let c0 = Char.code (String.unsafe_get str 0) in
+ let c1 = Char.code (String.unsafe_get str 1) in
+ let c2 = Char.code (String.unsafe_get str 2) in
+ let c3 = Char.code (String.unsafe_get str 3) in
+ Int64.of_int c3 +^
+ (Int64.shift_left (Int64.of_int c2) 8) +^
+ (Int64.shift_left (Int64.of_int c1) 16) +^
+ (Int64.shift_left (Int64.of_int c0) 24)
+
+let be32_of_int i =
+ let c0 = i &^ 0xffL in
+ let c1 = Int64.shift_right (i &^ 0xff00L) 8 in
+ let c2 = Int64.shift_right (i &^ 0xff0000L) 16 in
+ let c3 = Int64.shift_right (i &^ 0xff000000L) 24 in
+ let b = Bytes.create 4 in
+ Bytes.unsafe_set b 0 (Char.unsafe_chr (Int64.to_int c3));
+ Bytes.unsafe_set b 1 (Char.unsafe_chr (Int64.to_int c2));
+ Bytes.unsafe_set b 2 (Char.unsafe_chr (Int64.to_int c1));
+ Bytes.unsafe_set b 3 (Char.unsafe_chr (Int64.to_int c0));
+ Bytes.to_string b
+
+let int_of_be64 str =
+ assert (String.length str = 8);
+ let c0 = Char.code (String.unsafe_get str 0) in
+ let c1 = Char.code (String.unsafe_get str 1) in
+ let c2 = Char.code (String.unsafe_get str 2) in
+ let c3 = Char.code (String.unsafe_get str 3) in
+ let c4 = Char.code (String.unsafe_get str 4) in
+ let c5 = Char.code (String.unsafe_get str 5) in
+ let c6 = Char.code (String.unsafe_get str 6) in
+ let c7 = Char.code (String.unsafe_get str 7) in
+ Int64.of_int c7 +^
+ (Int64.shift_left (Int64.of_int c6) 8) +^
+ (Int64.shift_left (Int64.of_int c5) 16) +^
+ (Int64.shift_left (Int64.of_int c4) 24) +^
+ (Int64.shift_left (Int64.of_int c3) 32) +^
+ (Int64.shift_left (Int64.of_int c2) 40) +^
+ (Int64.shift_left (Int64.of_int c1) 48) +^
+ (Int64.shift_left (Int64.of_int c0) 56)
+
+let be64_of_int i =
+ let c0 = i &^ 0xffL in
+ let c1 = Int64.shift_right (i &^ 0xff00L) 8 in
+ let c2 = Int64.shift_right (i &^ 0xff0000L) 16 in
+ let c3 = Int64.shift_right (i &^ 0xff000000L) 24 in
+ let c4 = Int64.shift_right (i &^ 0xff00000000L) 32 in
+ let c5 = Int64.shift_right (i &^ 0xff0000000000L) 40 in
+ let c6 = Int64.shift_right (i &^ 0xff000000000000L) 48 in
+ let c7 = Int64.shift_right (i &^ 0xff00000000000000L) 56 in
+ let b = Bytes.create 8 in
+ Bytes.unsafe_set b 0 (Char.unsafe_chr (Int64.to_int c7));
+ Bytes.unsafe_set b 1 (Char.unsafe_chr (Int64.to_int c6));
+ Bytes.unsafe_set b 2 (Char.unsafe_chr (Int64.to_int c5));
+ Bytes.unsafe_set b 3 (Char.unsafe_chr (Int64.to_int c4));
+ Bytes.unsafe_set b 4 (Char.unsafe_chr (Int64.to_int c3));
+ Bytes.unsafe_set b 5 (Char.unsafe_chr (Int64.to_int c2));
+ Bytes.unsafe_set b 6 (Char.unsafe_chr (Int64.to_int c1));
+ Bytes.unsafe_set b 7 (Char.unsafe_chr (Int64.to_int c0));
+ Bytes.to_string b
+
type wrap_break_t = WrapEOS | WrapSpace | WrapNL
let rec wrap ?(chan = stdout) ?(indent = 0) str =
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index c0f1da30c..a07c1e6dc 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -143,10 +143,29 @@ val roundup64 : int64 -> int64 -> int64
val div_roundup64 : int64 -> int64 -> int64
(** [div_roundup64 i a] returns [i] rounded up to the next multiple of [a],
with the result divided by [a]. *)
+
+val int_of_le16 : string -> int64
+val le16_of_int : int64 -> string
+val int_of_be16 : string -> int64
+val be16_of_int : int64 -> string
val int_of_le32 : string -> int64
-(** Unpack a 4 byte string as a little endian 32 bit integer. *)
val le32_of_int : int64 -> string
-(** Pack a 32 bit integer a 4 byte string stored little endian. *)
+val int_of_be32 : string -> int64
+val be32_of_int : int64 -> string
+val int_of_le64 : string -> int64
+val le64_of_int : int64 -> string
+val int_of_be64 : string -> int64
+val be64_of_int : int64 -> string
+(** [int_of_X] functions unpack a string and return the equivalent integer.
+
+ [X_of_int] functions pack an integer into a string.
+
+ The value of [X] encodes whether the string is stored as
+ little endian [le] or big endian [be] and the size in bits
+ [16], [32] or [64].
+
+ On the OCaml side, 64 bit integers are always used so that you
+ can use the [.^] operators on them for bit manipulation. *)
val wrap : ?chan:out_channel -> ?indent:int -> string -> unit
(** Wrap text. *)
diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml
index 1003f931c..6bc74fb63 100644
--- a/common/mlstdutils/std_utils_tests.ml
+++ b/common/mlstdutils/std_utils_tests.ml
@@ -33,10 +33,22 @@ let test_subdirectory ctx =
assert_equal_string "bar" (subdirectory "/foo"
"/foo/bar");
assert_equal_string "bar/baz" (subdirectory "/foo"
"/foo/bar/baz")
-(* Test Common_utils.int_of_le32 and Common_utils.le32_of_int. *)
-let test_le32 ctx =
- assert_equal_int64 0x20406080L (int_of_le32 "\x80\x60\x40\x20");
- assert_equal_string "\x80\x60\x40\x20" (le32_of_int 0x20406080L)
+(* Test Std_utils.int_of_X and Std_utils.X_of_int byte swapping
+ * functions.
+ *)
+let rec test_byteswap ctx =
+ test_swap int_of_le16 le16_of_int 0x2040L "\x40\x20";
+ test_swap int_of_le32 le32_of_int 0x20406080L "\x80\x60\x40\x20";
+ test_swap int_of_le64 le64_of_int
+ 0x20406080A0C0E0F0L "\xF0\xE0\xC0\xA0\x80\x60\x40\x20";
+ test_swap int_of_be16 be16_of_int 0x2040L "\x20\x40";
+ test_swap int_of_be32 be32_of_int 0x20406080L "\x20\x40\x60\x80";
+ test_swap int_of_be64 be64_of_int
+ 0x20406080A0C0E0F0L "\x20\x40\x60\x80\xA0\xC0\xE0\xF0"
+
+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.String.is_prefix. *)
let test_string_is_prefix ctx =
@@ -84,7 +96,7 @@ let suite =
"mllib Std_utils" >:::
[
"subdirectory" >:: test_subdirectory;
- "numeric.le32" >:: test_le32;
+ "numeric.byteswap" >:: test_byteswap;
"strings.is_prefix" >:: test_string_is_prefix;
"strings.is_suffix" >:: test_string_is_suffix;
"strings.find" >:: test_string_find;
--
2.13.0