[m-rev.] for review: add conversion functions from bytes to 32-bit integers
Julien Fischer
jfischer at opturion.com
Wed Nov 1 15:44:04 AEDT 2017
For review by anyone.
--------------------
Add conversion functions from bytes (uint8s) to 32-bit integers.
library/int32.m:
library/uint32.m:
As above.
tests/hard_coded/Mmakefile:
tests/hard_coded/int32_from_bytes.{m,exp}:
tests/hard_coded/uint32_from_bytes.{m,exp}:
Test the new functions.
Julien.
diff --git a/library/int32.m b/library/int32.m
index 28c10d1..4513b3f 100644
--- a/library/int32.m
+++ b/library/int32.m
@@ -37,6 +37,20 @@
:- func to_int(int32) = int.
+ % from_bytes_le(Byte0, Byte1, Byte2, Byte3) = I32:
+ % I32 is the int32 whose bytes are given in little-endian order by the
+ % arguments from left-to-right (i.e. Byte0 is the least significant byte
+ % and Byte3 is the most significant byte).
+ %
+:- func from_bytes_le(uint8, uint8, uint8, uint8) = int32.
+
+ % from_bytes_be(Byte0, Byte1, Byte2, Byte3) = U32:
+ % I32 is the int32 whose bytes are given in big-endian order by the
+ % arguments in left-to-right order (i.e. Byte0 is the most significant
+ % byte and Byte3 is the least significant byte).
+ %
+:- func from_bytes_be(uint8, uint8, uint8, uint8) = int32.
+
%---------------------------------------------------------------------------%
% Less than.
@@ -342,6 +356,51 @@ to_int(_) = _ :-
%---------------------------------------------------------------------------%
+:- pragma foreign_proc("C",
+ from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (I32::out),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+ unsigned char *int32_bytes = (unsigned char *) &I32;
+#if defined(MR_BIG_ENDIAN)
+ int32_bytes[0] = Byte3;
+ int32_bytes[1] = Byte2;
+ int32_bytes[2] = Byte1;
+ int32_bytes[3] = Byte2;
+#else
+ int32_bytes[0] = Byte0;
+ int32_bytes[1] = Byte1;
+ int32_bytes[2] = Byte2;
+ int32_bytes[3] = Byte3;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+ from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (I32::out),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ I32 = (Byte3 & 0xff) << 24 |
+ (Byte2 & 0xff) << 16 |
+ (Byte1 & 0xff) << 8 |
+ (Byte0 & 0xff);
+").
+
+:- pragma foreign_proc("C#",
+ from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (I32::out),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ I32 = (Byte3 << 24 | Byte2 << 16 | Byte1 << 8 | Byte0);
+").
+
+from_bytes_le(_, _, _, _) = _ :-
+ sorry($module, "int32.from_bytes_le/4 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+from_bytes_be(Byte3, Byte2, Byte1, Byte0) =
+ from_bytes_le(Byte0, Byte1, Byte2, Byte3).
+
+%---------------------------------------------------------------------------%
+
X div Y = Div :-
Trunc = X // Y,
( if
diff --git a/library/uint32.m b/library/uint32.m
index 6254a30..80fbefa 100644
--- a/library/uint32.m
+++ b/library/uint32.m
@@ -35,6 +35,20 @@
:- func cast_to_int(uint32) = int.
+ % from_bytes_le(Byte0, Byte1, Byte2, Byte3) = U32:
+ % U32 is the uint32 whose bytes are given in little-endian order by the
+ % arguments from left-to-right (i.e. Byte0 is the least significant byte
+ % and Byte3 is the most significant byte).
+ %
+:- func from_bytes_le(uint8, uint8, uint8, uint8) = uint32.
+
+ % from_bytes_be(Byte0, Byte1, Byte2, Byte3) = U32:
+ % U32 is the uint32 whose bytes are given in big-endian order by the
+ % arguments in left-to-right order (i.e. Byte0 is the most significant
+ % byte and Byte3 is the least significant byte).
+ %
+:- func from_bytes_be(uint8, uint8, uint8, uint8) = uint32.
+
%---------------------------------------------------------------------------%
% Less than.
@@ -328,6 +342,51 @@ cast_to_int(_) = _ :-
%---------------------------------------------------------------------------%
+:- pragma foreign_proc("C",
+ from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (U32::out),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+ unsigned char *uint32_bytes = (unsigned char *) &U32;
+#if defined(MR_BIG_ENDIAN)
+ uint32_bytes[0] = Byte3;
+ uint32_bytes[1] = Byte2;
+ uint32_bytes[2] = Byte1;
+ uint32_bytes[3] = Byte2;
+#else
+ uint32_bytes[0] = Byte0;
+ uint32_bytes[1] = Byte1;
+ uint32_bytes[2] = Byte2;
+ uint32_bytes[3] = Byte3;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+ from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (U32::out),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ U32 = (Byte3 & 0xff) << 24 |
+ (Byte2 & 0xff) << 16 |
+ (Byte1 & 0xff) << 8 |
+ (Byte0 & 0xff);
+").
+
+:- pragma foreign_proc("C#",
+ from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (U32::out),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ U32 = (uint) (Byte3 << 24 | Byte2 << 16 | Byte1 << 8 | Byte0);
+").
+
+from_bytes_le(_, _, _, _) = _ :-
+ sorry($module, "uint32.from_bytes_le/4 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+from_bytes_be(Byte3, Byte2, Byte1, Byte0) =
+ from_bytes_le(Byte0, Byte1, Byte2, Byte3).
+
+%---------------------------------------------------------------------------%
+
X div Y = X // Y.
:- pragma inline('//'/2).
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 15dadc6..4bdef3a 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -174,6 +174,7 @@ ORDINARY_PROGS = \
int_fold_up_down \
int_range_ops \
int16_from_bytes \
+ int32_from_bytes \
integer_int16_conv \
integer_int32_conv \
integer_int8_conv \
@@ -375,8 +376,9 @@ ORDINARY_PROGS = \
type_to_term \
type_to_term_bug \
uc_export_enum \
- uint16_switch_test \
uint16_from_bytes \
+ uint16_switch_test \
+ uint32_from_bytes \
uint32_switch_test \
uint8_switch_test \
uint_switch_test \
diff --git a/tests/hard_coded/int32_from_bytes.exp b/tests/hard_coded/int32_from_bytes.exp
index e69de29..54fd865 100644
--- a/tests/hard_coded/int32_from_bytes.exp
+++ b/tests/hard_coded/int32_from_bytes.exp
@@ -0,0 +1,8 @@
+-16777216i32
+16711680i32
+65280i32
+255i32
+255i32
+65280i32
+16711680i32
+-16777216i32
diff --git a/tests/hard_coded/int32_from_bytes.m b/tests/hard_coded/int32_from_bytes.m
index e69de29..a09c700 100644
--- a/tests/hard_coded/int32_from_bytes.m
+++ b/tests/hard_coded/int32_from_bytes.m
@@ -0,0 +1,29 @@
+:- module int32_from_bytes.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int32.
+
+main(!IO) :-
+ Test1 = int32.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0xffu8),
+ io.write_line(Test1, !IO),
+ Test2 = int32.from_bytes_le(0x00u8, 0x00u8, 0xffu8, 0x00u8),
+ io.write_line(Test2, !IO),
+ Test3 = int32.from_bytes_le(0x00u8, 0xffu8, 0x00u8, 0x00u8),
+ io.write_line(Test3, !IO),
+ Test4 = int32.from_bytes_le(0xffu8, 0x00u8, 0x00u8, 0x00u8),
+ io.write_line(Test4, !IO),
+
+ Test5 = int32.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0xffu8),
+ io.write_line(Test5, !IO),
+ Test6 = int32.from_bytes_be(0x00u8, 0x00u8, 0xffu8, 0x00u8),
+ io.write_line(Test6, !IO),
+ Test7 = int32.from_bytes_be(0x00u8, 0xffu8, 0x00u8, 0x00u8),
+ io.write_line(Test7, !IO),
+ Test8 = int32.from_bytes_be(0xffu8, 0x00u8, 0x00u8, 0x00u8),
+ io.write_line(Test8, !IO).
diff --git a/tests/hard_coded/uint32_from_bytes.exp b/tests/hard_coded/uint32_from_bytes.exp
index e69de29..f3ac7ea 100644
--- a/tests/hard_coded/uint32_from_bytes.exp
+++ b/tests/hard_coded/uint32_from_bytes.exp
@@ -0,0 +1,8 @@
+4278190080u32
+16711680u32
+65280u32
+255u32
+255u32
+65280u32
+16711680u32
+4278190080u32
diff --git a/tests/hard_coded/uint32_from_bytes.m b/tests/hard_coded/uint32_from_bytes.m
index e69de29..ca2fd4a 100644
--- a/tests/hard_coded/uint32_from_bytes.m
+++ b/tests/hard_coded/uint32_from_bytes.m
@@ -0,0 +1,29 @@
+:- module uint32_from_bytes.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module uint32.
+
+main(!IO) :-
+ Test1 = uint32.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0xffu8),
+ io.write_line(Test1, !IO),
+ Test2 = uint32.from_bytes_le(0x00u8, 0x00u8, 0xffu8, 0x00u8),
+ io.write_line(Test2, !IO),
+ Test3 = uint32.from_bytes_le(0x00u8, 0xffu8, 0x00u8, 0x00u8),
+ io.write_line(Test3, !IO),
+ Test4 = uint32.from_bytes_le(0xffu8, 0x00u8, 0x00u8, 0x00u8),
+ io.write_line(Test4, !IO),
+
+ Test5 = uint32.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0xffu8),
+ io.write_line(Test5, !IO),
+ Test6 = uint32.from_bytes_be(0x00u8, 0x00u8, 0xffu8, 0x00u8),
+ io.write_line(Test6, !IO),
+ Test7 = uint32.from_bytes_be(0x00u8, 0xffu8, 0x00u8, 0x00u8),
+ io.write_line(Test7, !IO),
+ Test8 = uint32.from_bytes_be(0xffu8, 0x00u8, 0x00u8, 0x00u8),
+ io.write_line(Test8, !IO).
More information about the reviews
mailing list