mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
More library predicates for 64-bit integers.
library/io.m:
Add predicates for writing 64-bit integers to binary streams.
library/int64.m:
Add reverse_bytes/1.
library/uint64.m:
Add reverse_bytes/1 and cast_from_int64/1.
runtime/mercury_int.h:
Add MR_uint64_reverse_bytes.
tests/hard_coded/write_binary_multibyte_int.{m,exp}:
Extend this test to cover 64-bit integers.
This commit is contained in:
@@ -221,6 +221,12 @@
|
||||
%
|
||||
:- func \ (int64::in) = (int64::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(int64) = int64.
|
||||
|
||||
:- func min_int64 = int64.
|
||||
|
||||
:- func max_int64 = int64.
|
||||
@@ -486,6 +492,42 @@ odd(X) :-
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
reverse_bytes(A::in) = (B::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
|
||||
"
|
||||
B = (int64_t) MR_uint64_reverse_bytes((uint64_t)A);
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("C#",
|
||||
reverse_bytes(A::in) = (B::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe],
|
||||
"
|
||||
ulong u_A = (ulong) A;
|
||||
|
||||
B = (long) ((u_A & 0x00000000000000ffUL) << 56 |
|
||||
(u_A & 0x000000000000ff00UL) << 40 |
|
||||
(u_A & 0x0000000000ff0000UL) << 24 |
|
||||
(u_A & 0x00000000ff000000UL) << 8 |
|
||||
(u_A & 0x000000ff00000000UL) >> 8 |
|
||||
(u_A & 0x0000ff0000000000UL) >> 24 |
|
||||
(u_A & 0x00ff000000000000UL) >> 40 |
|
||||
(u_A & 0xff00000000000000UL) >> 56);
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("Java",
|
||||
reverse_bytes(A::in) = (B::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe],
|
||||
"
|
||||
B = java.lang.Long.reverseBytes(A);
|
||||
").
|
||||
|
||||
:- pragma no_determinism_warning(reverse_bytes/1).
|
||||
reverse_bytes(_) = _ :-
|
||||
sorry($module, "int64.reverse_bytes/1 NYI for Erlang").
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
min_int64 = -9_223_372_036_854_775_808_i64.
|
||||
|
||||
max_int64 = 9_223_372_036_854_775_807_i64.
|
||||
|
||||
233
library/io.m
233
library/io.m
@@ -1120,6 +1120,32 @@
|
||||
:- pred write_binary_uint32_be(io.binary_output_stream::in, uint32::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
%---------------------%
|
||||
|
||||
:- pred write_binary_int64(int64::in, io::di, io::uo) is det.
|
||||
:- pred write_binary_int64(io.binary_output_stream::in, int64::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pred write_binary_int64_le(int64::in, io::di, io::uo) is det.
|
||||
:- pred write_binary_int64_le(io.binary_output_stream::in, int64::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pred write_binary_int64_be(int64::in, io::di, io::uo) is det.
|
||||
:- pred write_binary_int64_be(io.binary_output_stream::in, int64::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pred write_binary_uint64(uint64::in, io::di, io::uo) is det.
|
||||
:- pred write_binary_uint64(io.binary_output_stream::in, uint64::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pred write_binary_uint64_le(uint64::in, io::di, io::uo) is det.
|
||||
:- pred write_binary_uint64_le(io.binary_output_stream::in, uint64::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pred write_binary_uint64_be(uint64::in, io::di, io::uo) is det.
|
||||
:- pred write_binary_uint64_be(io.binary_output_stream::in, uint64::in,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
%---------------------%
|
||||
|
||||
% Write a bitmap to the current binary output stream
|
||||
@@ -1934,6 +1960,7 @@
|
||||
:- import_module uint8.
|
||||
:- import_module uint16.
|
||||
:- import_module uint32.
|
||||
:- import_module uint64.
|
||||
|
||||
:- use_module rtti_implementation.
|
||||
:- use_module table_builtin.
|
||||
@@ -8099,6 +8126,34 @@ write_binary_uint32_be(UInt32, !IO) :-
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_binary_int64(Int64, !IO) :-
|
||||
UInt64 = uint64.cast_from_int64(Int64),
|
||||
write_binary_uint64(UInt64, !IO).
|
||||
|
||||
write_binary_int64_le(Int64, !IO) :-
|
||||
UInt64 = uint64.cast_from_int64(Int64),
|
||||
write_binary_uint64_le(UInt64, !IO).
|
||||
|
||||
write_binary_int64_be(Int64, !IO) :-
|
||||
UInt64 = uint64.cast_from_int64(Int64),
|
||||
write_binary_uint64_be(UInt64, !IO).
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_binary_uint64(UInt64, !IO) :-
|
||||
binary_output_stream(Stream, !IO),
|
||||
write_binary_uint64(Stream, UInt64, !IO).
|
||||
|
||||
write_binary_uint64_le(UInt64, !IO) :-
|
||||
binary_output_stream(Stream, !IO),
|
||||
write_binary_uint64_le(Stream, UInt64, !IO).
|
||||
|
||||
write_binary_uint64_be(UInt64, !IO) :-
|
||||
binary_output_stream(Stream, !IO),
|
||||
write_binary_uint64_be(Stream, UInt64, !IO).
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_bitmap(Bitmap, !IO) :-
|
||||
binary_output_stream(Stream, !IO),
|
||||
write_bitmap(Stream, Bitmap, !IO).
|
||||
@@ -8840,6 +8895,184 @@ write_binary_uint32_be(binary_output_stream(Stream), UInt32, !IO) :-
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_binary_int64(Stream, Int64, !IO) :-
|
||||
UInt64 = uint64.cast_from_int64(Int64),
|
||||
write_binary_uint64(Stream, UInt64, !IO).
|
||||
|
||||
write_binary_uint64(binary_output_stream(Stream), UInt64, !IO) :-
|
||||
do_write_binary_uint64(Stream, UInt64, Error, !IO),
|
||||
throw_on_output_error(Error, !IO).
|
||||
|
||||
:- pred do_write_binary_uint64(stream::in, uint64::in, system_error::out,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
do_write_binary_uint64(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
if (MR_WRITE(*Stream, (unsigned char *)(&U64), 8) != 8) {
|
||||
Error = errno;
|
||||
} else {
|
||||
Error = 0;
|
||||
}
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("Java",
|
||||
do_write_binary_uint64(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
try {
|
||||
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
||||
buffer.order(java.nio.ByteOrder.nativeOrder());
|
||||
buffer.putLong(U64);
|
||||
((io.MR_BinaryOutputFile) Stream).write(buffer.array(), 0, 8);
|
||||
Error = null;
|
||||
} catch (java.io.IOException e) {
|
||||
Error = e;
|
||||
}
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("C#",
|
||||
do_write_binary_uint64(Stream::in, U64::in, Error::out, _IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
byte[] bytes = BitConverter.GetBytes(U64);
|
||||
try {
|
||||
Stream.stream.Write(bytes, 0, 8);
|
||||
Error = null;
|
||||
} catch (System.Exception e) {
|
||||
Error = e;
|
||||
}
|
||||
").
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_binary_int64_le(Stream, Int64, !IO) :-
|
||||
UInt64 = uint64.cast_from_int64(Int64),
|
||||
write_binary_uint64_le(Stream, UInt64, !IO).
|
||||
|
||||
write_binary_uint64_le(binary_output_stream(Stream), UInt64, !IO) :-
|
||||
do_write_binary_uint64_le(Stream, UInt64, Error, !IO),
|
||||
throw_on_output_error(Error, !IO).
|
||||
|
||||
:- pred do_write_binary_uint64_le(stream::in, uint64::in, system_error::out,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
do_write_binary_uint64_le(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
#if defined(MR_BIG_ENDIAN)
|
||||
U64 = MR_uint64_reverse_bytes(U64);
|
||||
#endif
|
||||
|
||||
if (MR_WRITE(*Stream, (unsigned char *)(&U64), 8) != 8) {
|
||||
Error = errno;
|
||||
} else {
|
||||
Error = 0;
|
||||
}
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("Java",
|
||||
do_write_binary_uint64_le(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
try {
|
||||
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
||||
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
||||
buffer.putLong(U64);
|
||||
((io.MR_BinaryOutputFile) Stream).write(buffer.array(), 0, 8);
|
||||
Error = null;
|
||||
} catch (java.io.IOException e) {
|
||||
Error = e;
|
||||
}
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("C#",
|
||||
do_write_binary_uint64_le(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
byte[] bytes = BitConverter.GetBytes(U64);
|
||||
if (!BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
try {
|
||||
Stream.stream.Write(bytes, 0, 8);
|
||||
Error = null;
|
||||
} catch (System.Exception e) {
|
||||
Error = e;
|
||||
}
|
||||
").
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_binary_int64_be(Stream, Int64, !IO) :-
|
||||
UInt64 = uint64.cast_from_int64(Int64),
|
||||
write_binary_uint64_be(Stream, UInt64, !IO).
|
||||
|
||||
write_binary_uint64_be(binary_output_stream(Stream), UInt64, !IO) :-
|
||||
do_write_binary_uint64_be(Stream, UInt64, Error, !IO),
|
||||
throw_on_output_error(Error, !IO).
|
||||
|
||||
:- pred do_write_binary_uint64_be(stream::in, uint64::in, system_error::out,
|
||||
io::di, io::uo) is det.
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
do_write_binary_uint64_be(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
#if defined(MR_LITTLE_ENDIAN)
|
||||
U64 = MR_uint64_reverse_bytes(U64);
|
||||
#endif
|
||||
|
||||
if (MR_WRITE(*Stream, (unsigned char *)(&U64), 8) != 8) {
|
||||
Error = errno;
|
||||
} else {
|
||||
Error = 0;
|
||||
}
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("Java",
|
||||
do_write_binary_uint64_be(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
try {
|
||||
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
||||
// Order in a byte buffer is big endian by default.
|
||||
buffer.putLong(U64);
|
||||
((io.MR_BinaryOutputFile) Stream).write(buffer.array(), 0, 8);
|
||||
Error = null;
|
||||
} catch (java.io.IOException e) {
|
||||
Error = e;
|
||||
}
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("C#",
|
||||
do_write_binary_uint64_be(Stream::in, U64::in, Error::out,
|
||||
_IO0::di, _IO::uo),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
|
||||
"
|
||||
byte[] bytes = BitConverter.GetBytes(U64);
|
||||
if (BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
try {
|
||||
Stream.stream.Write(bytes, 0, 8);
|
||||
Error = null;
|
||||
} catch (System.Exception e) {
|
||||
Error = e;
|
||||
}
|
||||
").
|
||||
|
||||
%---------------------%
|
||||
|
||||
write_bitmap(binary_output_stream(Stream), Bitmap, !IO) :-
|
||||
( if NumBytes = Bitmap ^ num_bytes then
|
||||
do_write_bitmap(Stream, Bitmap, 0, NumBytes, Error, !IO),
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
:- func cast_to_int(uint64) = int.
|
||||
|
||||
:- func cast_from_int64(int64) = uint64.
|
||||
|
||||
% from_bytes_le(Byte0, Byte1, ..., Byte7) = U64:
|
||||
% U64 is the uint64 whose bytes are given in little-endian order by the
|
||||
% arguments from left-to-right (i.e. Byte0 is the least significant byte
|
||||
@@ -191,6 +193,12 @@
|
||||
%
|
||||
:- func \ (uint64::in) = (uint64::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(uint64) = uint64.
|
||||
|
||||
:- func max_uint64 = uint64.
|
||||
|
||||
% Convert a uint64 to a pretty_printer.doc for formatting.
|
||||
@@ -309,6 +317,34 @@ cast_to_int(_) = _ :-
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
cast_from_int64(I64::in) = (U64::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
|
||||
does_not_affect_liveness],
|
||||
"
|
||||
U64 = (uint64_t) I64;
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("C#",
|
||||
cast_from_int64(I64::in) = (U64::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe],
|
||||
"
|
||||
U64 = (ulong) I64;
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("Java",
|
||||
cast_from_int64(I64::in) = (U64::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe],
|
||||
"
|
||||
U64 = I64;
|
||||
").
|
||||
|
||||
:- pragma no_determinism_warning(cast_from_int64/1).
|
||||
cast_from_int64(_) = _ :-
|
||||
sorry($module, "uint64.cast_from_int64/1 NYI for Erlang").
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
|
||||
Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (U64::out),
|
||||
@@ -438,6 +474,32 @@ odd(X) :-
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
:- pragma foreign_proc("C",
|
||||
reverse_bytes(A::in) = (B::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
|
||||
"
|
||||
B = MR_uint64_reverse_bytes(A);
|
||||
").
|
||||
|
||||
:- pragma foreign_proc("Java",
|
||||
reverse_bytes(A::in) = (B::out),
|
||||
[will_not_call_mercury, promise_pure, thread_safe],
|
||||
"
|
||||
B = java.lang.Long.reverseBytes(A);
|
||||
").
|
||||
|
||||
reverse_bytes(A) = B :-
|
||||
B = ((A /\ 0x_0000_0000_0000_00ff_u64) << 56) \/
|
||||
((A /\ 0x_0000_0000_0000_ff00_u64) << 40) \/
|
||||
((A /\ 0x_0000_0000_00ff_0000_u64) << 24) \/
|
||||
((A /\ 0x_0000_0000_ff00_0000_u64) << 8) \/
|
||||
((A /\ 0x_0000_00ff_0000_0000_u64) >> 8) \/
|
||||
((A /\ 0x_0000_ff00_0000_0000_u64) >> 24) \/
|
||||
((A /\ 0x_00ff_0000_0000_0000_u64) >> 40) \/
|
||||
((A /\ 0x_ff00_0000_0000_0000_u64) >> 56).
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
max_uint64 = 18_446_744_073_709_551_615_u64.
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
@@ -114,4 +114,20 @@ extern MR_Integer MR_hash_uint64(uint64_t);
|
||||
(U & UINT32_C(0xff000000)) >> 24 )
|
||||
#endif
|
||||
|
||||
#if defined(MR_GNUC) || defined(MR_CLANG)
|
||||
#define MR_uint64_reverse_bytes(U) __builtin_bswap64((U))
|
||||
#elif defined(MR_MSVC)
|
||||
#define MR_uint64_reverse_bytes(U) _byteswap_uint64((UU))
|
||||
#else
|
||||
#define MR_uint64_reverse_bytes(U) \
|
||||
((U & UINT64_C(0x00000000000000ff)) << 56 | \
|
||||
(U & UINT64_C(0x000000000000ff00)) << 40 | \
|
||||
(U & UINT64_C(0x0000000000ff0000)) << 24 | \
|
||||
(U & UINT64_C(0x00000000ff000000)) << 8 | \
|
||||
(U & UINT64_C(0x000000ff00000000)) >> 8 | \
|
||||
(U & UINT64_C(0x0000ff0000000000)) >> 24 | \
|
||||
(U & UINT64_C(0x00ff000000000000)) >> 40 | \
|
||||
(U & UINT64_C(0xff00000000000000)) >> 56)
|
||||
#endif
|
||||
|
||||
#endif // not MERCURY_INT_H
|
||||
|
||||
@@ -1 +1,56 @@
|
||||
0x0a 0x0b 0x0b 0x0a 0xaa 0xbb 0xbb 0xaa 0x0a 0x0b 0x0c 0x0d 0x0d 0x0c 0x0b 0x0a 0xaa 0xbb 0xcc 0xdd 0xdd 0xcc 0xbb 0xaa
|
||||
0x0a
|
||||
0x0b
|
||||
0x0b
|
||||
0x0a
|
||||
0xaa
|
||||
0xbb
|
||||
0xbb
|
||||
0xaa
|
||||
0x0a
|
||||
0x0b
|
||||
0x0c
|
||||
0x0d
|
||||
0x0d
|
||||
0x0c
|
||||
0x0b
|
||||
0x0a
|
||||
0xaa
|
||||
0xbb
|
||||
0xcc
|
||||
0xdd
|
||||
0xdd
|
||||
0xcc
|
||||
0xbb
|
||||
0xaa
|
||||
0x0a
|
||||
0x0b
|
||||
0x0c
|
||||
0x0d
|
||||
0x0e
|
||||
0x0f
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0x0f
|
||||
0x0e
|
||||
0x0d
|
||||
0x0c
|
||||
0x0b
|
||||
0x0a
|
||||
0xaa
|
||||
0xbb
|
||||
0xcc
|
||||
0xdd
|
||||
0xee
|
||||
0xff
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0x00
|
||||
0xff
|
||||
0xee
|
||||
0xdd
|
||||
0xcc
|
||||
0xbb
|
||||
0xaa
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
% vim: ft=mercury ts=4 sw=4 et
|
||||
%---------------------------------------------------------------------------%
|
||||
%
|
||||
% Test writing of int16, uint16, in32 and uint32 to binary file streams.
|
||||
% Test writing of int16, uint16, int32, uint32, int64 and uint64 to binary file
|
||||
% streams.
|
||||
|
||||
:- module write_binary_multibyte_int.
|
||||
:- interface.
|
||||
@@ -44,6 +45,10 @@ main_2(FileName, !IO) :-
|
||||
io.write_binary_int32_be(OutputFile, 0x0d0c0b0a_i32, !IO),
|
||||
io.write_binary_uint32_le(OutputFile, 0xddccbbaa_u32, !IO),
|
||||
io.write_binary_uint32_be(OutputFile, 0xddccbbaa_u32, !IO),
|
||||
io.write_binary_int64_le(OutputFile, 0x0f0e0d0c0b0a_i64, !IO),
|
||||
io.write_binary_int64_be(OutputFile, 0x0f0e0d0c0b0a_i64, !IO),
|
||||
io.write_binary_uint64_le(OutputFile, 0xffeeddccbbaa_u64, !IO),
|
||||
io.write_binary_uint64_be(OutputFile, 0xffeeddccbbaa_u64, !IO),
|
||||
io.close_binary_output(OutputFile, !IO),
|
||||
|
||||
io.open_binary_input(FileName, OpenInputResult, !IO),
|
||||
@@ -53,7 +58,7 @@ main_2(FileName, !IO) :-
|
||||
(
|
||||
ReadResult = ok(Bytes),
|
||||
io.close_binary_input(InputFile, !IO),
|
||||
io.write_list(Bytes, " ", print_byte, !IO),
|
||||
io.write_list(Bytes, "\n", print_byte, !IO),
|
||||
io.nl(!IO)
|
||||
;
|
||||
ReadResult = error(IO_Error),
|
||||
|
||||
Reference in New Issue
Block a user