[m-rev.] for review: add a reverse_bytes/1 function for the 16- and 32-bit types

Julien Fischer jfischer at opturion.com
Fri Sep 22 11:06:26 AEST 2017


Add a reverse_bytes/1 function for the 16- and 32-bit types.

Add functions for reversing the bytes in the int16, int32, uint16 and uint32
types.  These are intended for use in implementing endianness conversions.

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

Julien.

diff --git a/library/int16.m b/library/int16.m
index 359bbe9..651681d 100644
--- a/library/int16.m
+++ b/library/int16.m
@@ -195,6 +195,12 @@
      %
  :- func \ (int16::in) = (int16::uo) is det.

+    % reverse_bytes(A) = B:
+    % B is the value that results from reversing the bytes in the
+    % representation of A.
+    %
+:- func reverse_bytes(int16) = int16.
+
  :- func min_int16 = int16.

  :- func max_int16 = int16.
@@ -388,6 +394,37 @@ max_int16 = 32_767_i16.

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

+:- pragma foreign_proc("C",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+#if defined(MR_GNUC) || defined(MR_CLANG)
+    B = (int16_t) __builtin_bswap16((uint16_t)A);
+#else
+    B = ((uint16_t)A >> 8) | (A << 8);
+#endif
+").
+
+:- pragma foreign_proc("C#",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = (short) ((A & 0x00ffU) << 8 | (A & 0xff00U) >> 8);
+").
+
+:- pragma foreign_proc("Java",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = java.lang.Short.reverseBytes(A);
+").
+
+:- pragma no_determinism_warning(reverse_bytes/1).
+reverse_bytes(_) = _ :-
+    sorry($module, "int16.reverse_bytes/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
  int16_to_doc(X) = str(string.int16_to_string(X)).

  %---------------------------------------------------------------------------%
diff --git a/library/int32.m b/library/int32.m
index 694766f..156db96 100644
--- a/library/int32.m
+++ b/library/int32.m
@@ -193,6 +193,12 @@
      %
  :- func \ (int32::in) = (int32::uo) is det.

+    % reverse_bytes(A) = B:
+    % B is the value that results from reversing the bytes in the
+    % representation of A.
+    %
+:- func reverse_bytes(int32) = int32.
+
  :- func min_int32 = int32.

  :- func max_int32 = int32.
@@ -408,6 +414,46 @@ odd(X) :-

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

+:- pragma foreign_proc("C",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+#if defined(MR_GNUC) || defined(MR_CLANG)
+    B = (int32_t) __builtin_bswap32(A);
+#else
+    uint32_t u_A = A;
+    B = (int32_t) ((u_A & UINT32_C(0x000000ff)) << 24 |
+                   (u_A & UINT32_C(0x0000ff00)) << 8  |
+                   (u_A & UINT32_C(0x00ff0000)) >> 8  |
+                   (u_A & UINT32_C(0xff000000)) >> 24);
+#endif
+").
+
+:- pragma foreign_proc("C#",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    uint u_A = (uint) A;
+
+    B = (int) ((u_A & 0x000000ffU) << 24  |
+               (u_A & 0x0000ff00U) << 8   |
+               (u_A & 0x00ff0000U) >> 8   |
+               (u_A & 0xff000000U) >> 24);
+").
+
+:- pragma foreign_proc("Java",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = java.lang.Integer.reverseBytes(A);
+").
+
+:- pragma no_determinism_warning(reverse_bytes/1).
+reverse_bytes(_) = _ :-
+    sorry($module, "int32.reverse_bytes/1 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
  min_int32 = -2_147_483_648_i32.

  max_int32 = 2_147_483_647_i32.
diff --git a/library/uint16.m b/library/uint16.m
index 4c04057..a924975 100644
--- a/library/uint16.m
+++ b/library/uint16.m
@@ -177,6 +177,12 @@
      %
  :- func \ (uint16::in) = (uint16::uo) is det.

+    % reverse_bytes(A) = B:
+    % B is the value that results from reversing the bytes in the
+    % representation of A.
+    %
+:- func reverse_bytes(uint16) = uint16.
+
  :- func max_uint16 = uint16.

      % Convert a uint16 to a pretty_printer.doc for formatting.
@@ -328,6 +334,29 @@ odd(X) :-

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

+:- pragma foreign_proc("C",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+#if defined(MR_GNUC) || defined(MR_CLANG)
+    B = __builtin_bswap16(A);
+#else
+    B = (A >> 8) | (A << 8);
+#endif
+").
+
+:- pragma foreign_proc("Java",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = java.lang.Short.reverseBytes(A);
+").
+
+reverse_bytes(A) = B :-
+    B = ((A /\ 0x_00ff_u16) << 8) \/ ((A /\0x_ff00_u16) >> 8).
+
+%---------------------------------------------------------------------------%
+
  max_uint16 = 65_535_u16.

  %---------------------------------------------------------------------------%
diff --git a/library/uint32.m b/library/uint32.m
index f285750..5cd3a4f 100644
--- a/library/uint32.m
+++ b/library/uint32.m
@@ -175,6 +175,12 @@
      %
  :- func \ (uint32::in) = (uint32::uo) is det.

+    % reverse_bytes(A) = B:
+    % B is the value that results from reversing the bytes in the
+    % representation of A.
+    %
+:- func reverse_bytes(uint32) = uint32.
+
  :- func max_uint32 = uint32.

      % Convert a uint32 to a pretty_printer.doc for formatting.
@@ -353,6 +359,35 @@ odd(X) :-

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

+:- pragma foreign_proc("C",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+#if defined(MR_GNUC) || defined(MR_CLANG)
+    B = __builtin_bswap32(A);
+#else
+    B = (A & UINT32_C(0x000000ff)) << 24 |
+        (A & UINT32_C(0x0000ff00)) << 8  |
+        (A & UINT32_C(0x00ff0000)) >> 8  |
+        (A & UINT32_C(0xff000000)) >> 24;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+    reverse_bytes(A::in) = (B::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    B = java.lang.Integer.reverseBytes(A);
+").
+
+reverse_bytes(A) = B :-
+    B = ((A /\ 0x_0000_00ff_u32) << 24) \/
+        ((A /\ 0x_0000_ff00_u32) << 8)  \/
+        ((A /\ 0x_00ff_0000_u32) >> 8)  \/
+        ((A /\ 0x_ff00_0000_u32) >> 24).
+
+%---------------------------------------------------------------------------%
+
  max_uint32 = 4_294_967_295_u32.

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


More information about the reviews mailing list