[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