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 7b8d65f66..f545c6f7a 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 820673764..686d4193f 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 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs