[m-rev.] for review: add conversion fucntions from bytes to 16-bit integers

Julien Fischer jfischer at opturion.com
Tue Oct 10 12:06:54 AEDT 2017


For review by anyone.

Note: I will add the 32-bit versions of these after this change has been
reviewed.

-----------------------

Add conversion functions from bytes (uint8s) to 16-bit integers.

library/int16.m:
library/uint16.m:
      As above.

tests/hard_coded/Mmakefile:
tests/hard_coded/int16_from_bytes.{m,exp}:
tests/hard_coded/uint16_from_bytes.{m,exp}:
      Test the new functions.

Julien.

diff --git a/library/int16.m b/library/int16.m
index 4399830..4ce54cf 100644
--- a/library/int16.m
+++ b/library/int16.m
@@ -37,6 +37,18 @@

  :- func to_int(int16) = int.

+    % from_bytes_le(LSB, MSB) = I16:
+    % I16 is the int16 whose least and most significant bytes are given by the
+    % uint8s LSB and MSB respectively.
+    %
+:- func from_bytes_le(uint8, uint8) = int16.
+
+    % from_bytes_be(MSB, LSB) = I16:
+    % I16 is the int16 whose least and most significant bytes are given by the
+    % uint8s LSB and MSB respectively.
+    %
+:- func from_bytes_be(uint8, uint8) = int16.
+
  %---------------------------------------------------------------------------%

      % Less than.
@@ -316,6 +328,44 @@ cast_from_uint16(_) = _ :-

  %---------------------------------------------------------------------------%

+:- pragma foreign_proc("C",
+    from_bytes_le(LSB::in, MSB::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    unsigned char *int16_bytes = (unsigned char *) &I16;
+#if defined(MR_BIG_ENDIAN)
+    int16_bytes[0] = MSB;
+    int16_bytes[1] = LSB;
+#else
+    int16_bytes[0] = LSB;
+    int16_bytes[1] = MSB;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+    from_bytes_le(LSB::in, MSB::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) (MSB << java.lang.Byte.SIZE | (LSB & 0x00ff));
+").
+
+:- pragma foreign_proc("C#",
+    from_bytes_le(LSB::in, MSB::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) (MSB << 8 | (LSB & 0x00ff));
+").
+
+from_bytes_le(_, _) = _ :-
+    sorry($module, "int16.from_bytes_le/2 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+from_bytes_be(MSB, LSB) =
+    from_bytes_le(LSB, MSB).
+
+%---------------------------------------------------------------------------%
+
  max(X, Y) =
      ( if X > Y then X else Y ).

diff --git a/library/uint16.m b/library/uint16.m
index 5a592a2..9d2c6e8 100644
--- a/library/uint16.m
+++ b/library/uint16.m
@@ -37,6 +37,18 @@

  :- func to_int(uint16) = int.

+    % from_bytes_le(LSB, MSB) = U16:
+    % U16 is the uint16 whose least and most significant bytes are given by the
+    % uint8s LSB and MSB respectively.
+    %
+:- func from_bytes_le(uint8, uint8) = uint16.
+
+    % from_bytes_be(MSB, LSB) = U16:
+    % U16 is the uint16 whose least and most significant bytes are given by the
+    % uint8s LSB and MSB respectively.
+    %
+:- func from_bytes_be(uint8, uint8) = uint16.
+
  %--------------------------------------------------------------------------%

      % Less than.
@@ -304,6 +316,44 @@ to_int(_) = _ :-

  %---------------------------------------------------------------------------%

+:- pragma foreign_proc("C",
+    from_bytes_le(LSB::in, MSB::in) = (U16::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    unsigned char *uint16_bytes = (unsigned char *) &U16;
+#if defined(MR_BIG_ENDIAN)
+    uint16_bytes[0] = MSB;
+    uint16_bytes[1] = LSB;
+#else
+    uint16_bytes[0] = LSB;
+    uint16_bytes[1] = MSB;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+    from_bytes_le(LSB::in, MSB::in) = (U16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U16 = (short) (MSB << java.lang.Byte.SIZE | (LSB & 0x00ff));
+").
+
+:- pragma foreign_proc("C#",
+    from_bytes_le(LSB::in, MSB::in) = (U16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U16 = (ushort) (MSB << 8 | (LSB & 0x00ff));
+").
+
+from_bytes_le(_, _) = _ :-
+    sorry($module, "uint16.from_bytes_le/2 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+from_bytes_be(MSB, LSB) =
+    from_bytes_le(LSB, MSB).
+
+%---------------------------------------------------------------------------%
+
  X div Y = X // Y.

  :- pragma inline('//'/2).
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 52758f2..55854fb 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -172,6 +172,7 @@ ORDINARY_PROGS =	\
  	inst_alias \
  	int_fold_up_down \
  	int_range_ops \
+	int16_from_bytes \
  	integer_int16_conv \
  	integer_int32_conv \
  	integer_int8_conv \
@@ -373,6 +374,7 @@ ORDINARY_PROGS =	\
  	type_to_term_bug \
  	uc_export_enum \
  	uint16_switch_test \
+	uint16_from_bytes \
  	uint32_switch_test \
  	uint8_switch_test \
  	uint_switch_test \
diff --git a/tests/hard_coded/int16_from_bytes.exp b/tests/hard_coded/int16_from_bytes.exp
index e69de29..62a8cd0 100644
--- a/tests/hard_coded/int16_from_bytes.exp
+++ b/tests/hard_coded/int16_from_bytes.exp
@@ -0,0 +1,4 @@
+-256i16
+255i16
+255i16
+-256i16
diff --git a/tests/hard_coded/int16_from_bytes.m b/tests/hard_coded/int16_from_bytes.m
index e69de29..0dc6eaf 100644
--- a/tests/hard_coded/int16_from_bytes.m
+++ b/tests/hard_coded/int16_from_bytes.m
@@ -0,0 +1,20 @@
+:- module int16_from_bytes.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int16.
+
+main(!IO) :-
+     Test1 = int16.from_bytes_le(0x00u8, 0xffu8),
+     io.write_line(Test1, !IO),
+     Test2 = int16.from_bytes_le(0xffu8, 0x00u8),
+     io.write_line(Test2, !IO),
+     Test3 = int16.from_bytes_be(0x00u8, 0xffu8),
+     io.write_line(Test3, !IO),
+     Test4 = int16.from_bytes_be(0xffu8, 0x00u8),
+     io.write_line(Test4, !IO).
diff --git a/tests/hard_coded/uint16_from_bytes.exp b/tests/hard_coded/uint16_from_bytes.exp
index e69de29..e57f651 100644
--- a/tests/hard_coded/uint16_from_bytes.exp
+++ b/tests/hard_coded/uint16_from_bytes.exp
@@ -0,0 +1,4 @@
+65280u16
+255u16
+255u16
+65280u16
diff --git a/tests/hard_coded/uint16_from_bytes.m b/tests/hard_coded/uint16_from_bytes.m
index e69de29..1bb34bf 100644
--- a/tests/hard_coded/uint16_from_bytes.m
+++ b/tests/hard_coded/uint16_from_bytes.m
@@ -0,0 +1,20 @@
+:- module uint16_from_bytes.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module uint16.
+
+main(!IO) :-
+     Test1 = uint16.from_bytes_le(0x00u8, 0xffu8),
+     io.write_line(Test1, !IO),
+     Test2 = uint16.from_bytes_le(0xffu8, 0x00u8),
+     io.write_line(Test2, !IO),
+     Test3 = uint16.from_bytes_be(0x00u8, 0xffu8),
+     io.write_line(Test3, !IO),
+     Test4 = uint16.from_bytes_be(0xffu8, 0x00u8),
+     io.write_line(Test4, !IO).


More information about the reviews mailing list