[m-rev.] for review: reading multibyte integers from binary file streams
Julien Fischer
jfischer at opturion.com
Tue Jan 8 12:43:43 AEDT 2019
Hi,
Any takers to review this one?
Cheers,
Julien.
On Fri, 4 Jan 2019, Julien Fischer wrote:
>
> For review by anyone.
>
> ---------------------
>
> Reading multibyte integers from binary file streams.
>
> Add predicates for reading multibyte integers from binary file streams. As
> with the corresponding predicates for writing multibyte integers to binary
> file
> streams, we provide versions for big-endian, little-endian and native byte
> orders.
>
> library/io.m:
> Add a new type that represents possibly incomplete results when reading
> from binary file streams.
>
> Add the new predicates.
>
> tests/hard_coded/Mmakefile:
> tests/hard_coded/read_binary_{int,uint}{16,32,64}.{m,exp}:
> Add tests of the new predicates.
>
> Julien.
>
> diff --git a/library/io.m b/library/io.m
> index d407c09..4b852c7 100644
> --- a/library/io.m
> +++ b/library/io.m
> @@ -108,6 +108,16 @@
> ; eof
> ; error(io.error).
>
> + % maybe_incomplete_result is used for multibyte values read from a
> binary
> + % stream where it is possible for the final element in the stream to be
> + % incomplete.
> + %
> +:- type maybe_incomplete_result(T)
> + ---> ok(T)
> + ; eof
> + ; incomplete(list(uint8))
> + ; error(io.error).
> +
> :- type read_result(T)
> ---> ok(T)
> ; eof
> @@ -872,6 +882,117 @@
> :- pred read_binary_uint8(io.binary_input_stream::in, io.result(uint8)::out,
> io::di, io::uo) is det.
>
> + % The following predicates read multibyte integer values from the
> current
> + % binary input stream or from the specified input stream.
> + %
> + % These names of these predicates have the form:
> + %
> + % read_binary_<TYPE><SUFFIX>
> + %
> + % where <TYPE> is the name of one of the Mercury multibyte fixed size
> + % integer types. <SUFFIX> is optional and specifies the byte order in
> + % which the integer value is read from the stream. It may be one of:
> + %
> + % no suffix - native byte order of the underlying platform.
> + % "_le" - little endian byte order.
> + % "_be" - big endian byte order.
> + %
> +:- pred read_binary_int16(maybe_incomplete_result(int16)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int16(io.binary_input_stream::in,
> + maybe_incomplete_result(int16)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_int16_le(maybe_incomplete_result(int16)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int16_le(io.binary_input_stream::in,
> + maybe_incomplete_result(int16)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_int16_be(maybe_incomplete_result(int16)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int16_be(io.binary_input_stream::in,
> + maybe_incomplete_result(int16)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint16(maybe_incomplete_result(uint16)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint16(io.binary_input_stream::in,
> + maybe_incomplete_result(uint16)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint16_le(maybe_incomplete_result(uint16)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint16_le(io.binary_input_stream::in,
> + maybe_incomplete_result(uint16)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint16_be(maybe_incomplete_result(uint16)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint16_be(io.binary_input_stream::in,
> + maybe_incomplete_result(uint16)::out, io::di, io::uo) is det.
> +
> +%---------------------%
> +
> +:- pred read_binary_int32(maybe_incomplete_result(int32)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int32(io.binary_input_stream::in,
> + maybe_incomplete_result(int32)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_int32_le(maybe_incomplete_result(int32)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int32_le(io.binary_input_stream::in,
> + maybe_incomplete_result(int32)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_int32_be(maybe_incomplete_result(int32)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int32_be(io.binary_input_stream::in,
> + maybe_incomplete_result(int32)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint32(maybe_incomplete_result(uint32)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint32(io.binary_input_stream::in,
> + maybe_incomplete_result(uint32)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint32_le(maybe_incomplete_result(uint32)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint32_le(io.binary_input_stream::in,
> + maybe_incomplete_result(uint32)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint32_be(maybe_incomplete_result(uint32)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint32_be(io.binary_input_stream::in,
> + maybe_incomplete_result(uint32)::out, io::di, io::uo) is det.
> +
> +%---------------------%
> +
> +:- pred read_binary_int64(maybe_incomplete_result(int64)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int64(io.binary_input_stream::in,
> + maybe_incomplete_result(int64)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_int64_le(maybe_incomplete_result(int64)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int64_le(io.binary_input_stream::in,
> + maybe_incomplete_result(int64)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_int64_be(maybe_incomplete_result(int64)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_int64_be(io.binary_input_stream::in,
> + maybe_incomplete_result(int64)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint64(maybe_incomplete_result(uint64)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint64(io.binary_input_stream::in,
> + maybe_incomplete_result(uint64)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint64_le(maybe_incomplete_result(uint64)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint64_le(io.binary_input_stream::in,
> + maybe_incomplete_result(uint64)::out, io::di, io::uo) is det.
> +
> +:- pred read_binary_uint64_be(maybe_incomplete_result(uint64)::out,
> + io::di, io::uo) is det.
> +:- pred read_binary_uint64_be(io.binary_input_stream::in,
> + maybe_incomplete_result(uint64)::out, io::di, io::uo) is det.
> +
> +%---------------------%
> +
> % Fill a bitmap from the current binary input stream
> % or from the specified binary input stream.
> % Return the number of bytes read. On end-of-file, the number of
> @@ -1977,6 +2098,9 @@
> :- import_module exception.
> :- import_module int.
> :- import_module int8.
> +:- import_module int16.
> +:- import_module int32.
> +:- import_module int64.
> :- import_module parser.
> :- import_module require.
> :- import_module stream.string_writer.
> @@ -2132,6 +2256,19 @@ using System.Security.Principal;
> :- pragma foreign_export_enum("Java", result_code/0,
> [prefix("ML_RESULT_CODE_"), uppercase]).
>
> +:- type maybe_incomplete_result_code
> + ---> ok
> + ; eof
> + ; incomplete
> + ; error.
> +
> +:- pragma foreign_export_enum("C", maybe_incomplete_result_code/0,
> + [prefix("ML_MAYBE_INCOMPLETE_RESULT_CODE_"), uppercase]).
> +:- pragma foreign_export_enum("C#", maybe_incomplete_result_code/0,
> + [prefix("ML_MAYBE_INCOMPLETE_RESULT_CODE_"), uppercase]).
> +:- pragma foreign_export_enum("Java", maybe_incomplete_result_code/0,
> + [prefix("ML_MAYBE_INCOMPLETE_RESULT_CODE_"), uppercase]).
> +
> % Reads a character (code point) from specified stream. This may
> % involve converting external character encodings into Mercury's
> % internal
> % character representation and (for text streams) converting OS line
> @@ -2383,6 +2520,825 @@ read_binary_uint8(binary_input_stream(Stream),
> Result, !IO) :-
> Result = error(io_error(Msg))
> ) .
>
> +%---------------------%
> +
> +read_binary_int16(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int16(Stream, Result, !IO).
> +
> +read_binary_int16(Stream, Result, !IO) :-
> + ( if native_byte_order_is_big_endian then
> + read_binary_int16_be(Stream, Result, !IO)
> + else
> + read_binary_int16_le(Stream, Result, !IO)
> + ).
> +
> +:- pred native_byte_order_is_big_endian is semidet.
> +
> +:- pragma foreign_proc("C",
> + native_byte_order_is_big_endian,
> + [promise_pure, will_not_call_mercury, thread_safe],
> +"
> + #if defined(MR_BIG_ENDIAN)
> + SUCCESS_INDICATOR = MR_TRUE;
> + #else
> + SUCCESS_INDICATOR = MR_FALSE;
> + #endif
> +").
> +
> +:- pragma foreign_proc("C#",
> + native_byte_order_is_big_endian,
> + [promise_pure, will_not_call_mercury, thread_safe],
> +"
> + SUCCESS_INDICATOR = !(BitConverter.IsLittleEndian);
> +").
> +
> +:- pragma foreign_proc("Java",
> + native_byte_order_is_big_endian,
> + [promise_pure, will_not_call_mercury, thread_safe],
> +"
> + SUCCESS_INDICATOR =
> + (java.nio.ByteOrder.nativeOrder() == java.nio.ByteOrder.BIG_ENDIAN);
> +").
> +
> +native_byte_order_is_big_endian :-
> + sorry($module,
> + "native_byte_order_is_big_endian/0 NYI for Erlang").
> +
> +%---------------------%
> +
> +read_binary_int16_le(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int16_le(Stream, Result, !IO).
> +
> +read_binary_int16_le(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint16_le(Stream, Result0, UInt16, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + Int16 = cast_from_uint16(UInt16),
> + Result = ok(Int16)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_int16_be(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int16_be(Stream, Result, !IO).
> +
> +read_binary_int16_be(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint16_le(Stream, Result0, UInt16LE, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + UInt16BE = reverse_bytes(UInt16LE),
> + Int16 = cast_from_uint16(UInt16BE),
> + Result = ok(Int16)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_uint16(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint16(Stream, Result, !IO).
> +
> +read_binary_uint16(Stream, Result, !IO) :-
> + ( if native_byte_order_is_big_endian then
> + read_binary_uint16_be(Stream, Result, !IO)
> + else
> + read_binary_uint16_le(Stream, Result, !IO)
> + ).
> +
> +%---------------------%
> +
> +read_binary_uint16_le(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint16_le(Stream, Result, !IO).
> +
> +read_binary_uint16_le(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint16_le(Stream, Result0, UInt16, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + Result = ok(UInt16)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +:- pred do_read_binary_uint16_le(stream::in,
> maybe_incomplete_result_code::out,
> + uint16::out, list(uint8)::out, system_error::out, io::di, io::uo) is
> det.
> +
> +:- pragma foreign_proc("C",
> + do_read_binary_uint16_le(Stream::in, Result::out, UInt16::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe,
> will_not_modify_trail],
> +"
> + unsigned char buffer[2];
> + size_t nread = MR_READ(*Stream, buffer, 2);
> + IncompleteBytes = MR_list_empty();
> +
> + if (nread < 2) {
> + UInt16 = 0;
> + if (MR_FERROR(*Stream)) {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR,
> + Error = errno;
> + } else if (nread > 0) {
> + int i;
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + IncompleteBytes = MR_list_cons(buffer[0], IncompleteBytes);
> + Error = 0;
> + } else {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + Error = 0;
> + }
> + } else {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + #if defined(MR_BIG_ENDIAN)
> + ((unsigned char *) &UInt16)[0] = buffer[1];
> + ((unsigned char *) &UInt16)[1] = buffer[0];
> + #else
> + UInt16 = *((uint16_t *) buffer);
> + #endif
> + Error = 0;
> + }
> +").
> +
> +:- pragma foreign_proc("C#",
> + do_read_binary_uint16_le(Stream::in, Result::out, UInt16::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe],
> +"
> + byte[] buffer = new byte[2];
> + io.MR_MercuryFileStruct mf = Stream;
> + UInt16 = 0;
> + IncompleteBytes = list.empty_list();
> +
> + int nread = 0;
> +
> + if (mf.putback != -1) {
> + buffer[nread] = (byte) mf.putback;
> + nread++;
> + mf.putback = -1;
> + }
> +
> + try {
> + for ( ; nread < 2; nread++) {
> + int b = mf.stream.ReadByte();
> + if (b == -1) {
> + break;
> + }
> + buffer[nread] = (byte) b;
> + }
> + if (nread < 2) {
> + if (nread > 0) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + IncompleteBytes = list.cons(buffer[0], IncompleteBytes);
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + UInt16 = (ushort) (buffer[1] << 8 | (buffer[0] & 0x00ff));
> + }
> + Error = null;
> + } catch (System.Exception e) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR;
> + Error = e;
> + }
> +").
> +
> +:- pragma foreign_proc("Java",
> + do_read_binary_uint16_le(Stream::in, Result::out, UInt16::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe],
> +"
> + byte[] buffer = new byte[2];
> + MR_BinaryInputFile mf = (MR_BinaryInputFile) Stream;
> + UInt16 = 0;
> + IncompleteBytes = list.empty_list();
> +
> + try {
> + int nread;
> + for (nread = 0; nread < 2; nread++) {
> + int next = mf.read_byte();
> + if (next == -1) {
> + break;
> + }
> + buffer[nread] = (byte) next;
> + }
> + if (nread < 2) {
> + if (nread > 0) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + IncompleteBytes = list.cons(buffer[0], IncompleteBytes);
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + UInt16 = (short) (buffer[1] << 8 | (buffer[0] & 0x00ff));
> + }
> + Error = null;
> + } catch (java.lang.Exception e) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR;
> + Error = e;
> + }
> +").
> +
> +do_read_binary_uint16_le(_, _, _, _, _, _, _) :-
> + sorry($module, "do_read_binary_uint16_le NYI for Erlang").
> +
> +%---------------------%
> +
> +read_binary_uint16_be(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint16_be(Stream, Result, !IO).
> +
> +read_binary_uint16_be(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint16_le(Stream, Result0, UInt16LE, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + UInt16BE = uint16.reverse_bytes(UInt16LE),
> + Result = ok(UInt16BE)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_int32(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int32(Stream, Result, !IO).
> +
> +read_binary_int32(Stream, Result, !IO) :-
> + ( if native_byte_order_is_big_endian then
> + read_binary_int32_be(Stream, Result, !IO)
> + else
> + read_binary_int32_le(Stream, Result, !IO)
> + ).
> +
> +%---------------------%
> +
> +read_binary_int32_le(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int32_le(Stream, Result, !IO).
> +
> +read_binary_int32_le(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint32_le(Stream, Result0, UInt32, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + Int32 = cast_from_uint32(UInt32),
> + Result = ok(Int32)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_int32_be(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int32_be(Stream, Result, !IO).
> +
> +read_binary_int32_be(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint32_le(Stream, Result0, UInt32LE, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + UInt32BE = reverse_bytes(UInt32LE),
> + Int32 = cast_from_uint32(UInt32BE),
> + Result = ok(Int32)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_uint32(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint32(Stream, Result, !IO).
> +
> +read_binary_uint32(Stream, Result, !IO) :-
> + ( if native_byte_order_is_big_endian then
> + read_binary_uint32_be(Stream, Result, !IO)
> + else
> + read_binary_uint32_le(Stream, Result, !IO)
> + ).
> +
> +%---------------------%
> +
> +read_binary_uint32_le(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint32_le(Stream, Result, !IO).
> +
> +read_binary_uint32_le(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint32_le(Stream, Result0, UInt32, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + Result = ok(UInt32)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +:- pred do_read_binary_uint32_le(stream::in,
> maybe_incomplete_result_code::out,
> + uint32::out, list(uint8)::out, system_error::out, io::di, io::uo) is
> det.
> +
> +:- pragma foreign_proc("C",
> + do_read_binary_uint32_le(Stream::in, Result::out, UInt32::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe,
> will_not_modify_trail],
> +"
> + unsigned char buffer[4];
> + size_t nread = MR_READ(*Stream, buffer, 4);
> + IncompleteBytes = MR_list_empty();
> +
> + if (nread < 4) {
> + UInt32 = 0;
> + if (MR_FERROR(*Stream)) {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR,
> + Error = errno;
> + } else if (nread > 0) {
> + int i;
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + for (i = nread - 1; i >= 0; i--) {
> + IncompleteBytes = MR_list_cons(buffer[i], IncompleteBytes);
> + }
> + Error = 0;
> + } else {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + Error = 0;
> + }
> + } else {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + #if defined(MR_BIG_ENDIAN)
> + ((unsigned char *) &UInt32)[0] = buffer[3];
> + ((unsigned char *) &UInt32)[1] = buffer[2];
> + ((unsigned char *) &UInt32)[2] = buffer[1];
> + ((unsigned char *) &UInt32)[3] = buffer[0];
> + #else
> + UInt32 = *((uint32_t *) buffer);
> + #endif
> + Error = 0;
> + }
> +").
> +
> +:- pragma foreign_proc("C#",
> + do_read_binary_uint32_le(Stream::in, Result::out, UInt32::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe],
> +"
> + byte[] buffer = new byte[4];
> + io.MR_MercuryFileStruct mf = Stream;
> + UInt32 = 0;
> + IncompleteBytes = list.empty_list();
> +
> + int nread = 0;
> +
> + if (mf.putback != -1) {
> + buffer[nread] = (byte) mf.putback;
> + nread++;
> + mf.putback = -1;
> + }
> +
> + try {
> + for ( ; nread < 4; nread++) {
> + int b = mf.stream.ReadByte();
> + if (b == -1) {
> + break;
> + }
> + buffer[nread] = (byte) b;
> + }
> + if (nread < 4) {
> + if (nread > 0) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + for (int i = nread - 1; i >= 0; i--) {
> + IncompleteBytes = list.cons(buffer[i], IncompleteBytes);
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + UInt32 = (uint) (buffer[3] << 24 | buffer[2] << 16 |
> + buffer[1] << 8 | buffer[0]);
> + }
> + Error = null;
> + } catch (System.Exception e) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR;
> + Error = e;
> + }
> +").
> +
> +:- pragma foreign_proc("Java",
> + do_read_binary_uint32_le(Stream::in, Result::out, UInt32::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe],
> +"
> + byte[] buffer = new byte[4];
> + MR_BinaryInputFile mf = (MR_BinaryInputFile) Stream;
> + UInt32 = 0;
> + IncompleteBytes = list.empty_list();
> +
> + try {
> + int nread;
> + for (nread = 0; nread < 4; nread++) {
> + int next = mf.read_byte();
> + if (next == -1) {
> + break;
> + }
> + buffer[nread] = (byte) next;
> + }
> + if (nread < 4) {
> + if (nread > 0) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + for (int i = nread - 1; i >= 0; i--) {
> + IncompleteBytes = list.cons(buffer[i], IncompleteBytes);
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + UInt32 =
> + (buffer[3] & 0xff) << 24 |
> + (buffer[2] & 0xff) << 16 |
> + (buffer[1] & 0xff) << 8 |
> + (buffer[0] & 0xff);
> + }
> + Error = null;
> + } catch (java.lang.Exception e) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR;
> + Error = e;
> + }
> +").
> +
> +do_read_binary_uint32_le(_, _, _, _, _, _, _) :-
> + sorry($module, "do_read_binary_uint32_le NYI for Erlang").
> +
> +%---------------------%
> +
> +read_binary_uint32_be(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint32_be(Stream, Result, !IO).
> +
> +read_binary_uint32_be(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint32_le(Stream, Result0, UInt32LE, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + UInt32BE = uint32.reverse_bytes(UInt32LE),
> + Result = ok(UInt32BE)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_int64(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int64(Stream, Result, !IO).
> +
> +read_binary_int64(Stream, Result, !IO) :-
> + ( if native_byte_order_is_big_endian then
> + read_binary_int64_be(Stream, Result, !IO)
> + else
> + read_binary_int64_le(Stream, Result, !IO)
> + ).
> +
> +%---------------------%
> +
> +read_binary_int64_le(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int64_le(Stream, Result, !IO).
> +
> +read_binary_int64_le(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint64_le(Stream, Result0, UInt64, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + Int64 = cast_from_uint64(UInt64),
> + Result = ok(Int64)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_int64_be(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_int64_be(Stream, Result, !IO).
> +
> +read_binary_int64_be(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint64_le(Stream, Result0, UInt64LE, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + UInt64BE = reverse_bytes(UInt64LE),
> + Int64 = cast_from_uint64(UInt64BE),
> + Result = ok(Int64)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> +read_binary_uint64(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint64(Stream, Result, !IO).
> +
> +read_binary_uint64(Stream, Result, !IO) :-
> + ( if native_byte_order_is_big_endian then
> + read_binary_uint64_be(Stream, Result, !IO)
> + else
> + read_binary_uint64_le(Stream, Result, !IO)
> + ).
> +
> +%---------------------%
> +
> +read_binary_uint64_le(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint64_le(Stream, Result, !IO).
> +
> +read_binary_uint64_le(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint64_le(Stream, Result0, UInt64, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + Result = ok(UInt64)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +:- pred do_read_binary_uint64_le(stream::in,
> maybe_incomplete_result_code::out,
> + uint64::out, list(uint8)::out, system_error::out, io::di, io::uo) is
> det.
> +
> +:- pragma foreign_proc("C",
> + do_read_binary_uint64_le(Stream::in, Result::out, UInt64::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe,
> will_not_modify_trail],
> +"
> + unsigned char buffer[8];
> + size_t nread = MR_READ(*Stream, buffer, 8);
> + IncompleteBytes = MR_list_empty();
> +
> + if (nread < 8) {
> + UInt64 = 0;
> + if (MR_FERROR(*Stream)) {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR,
> + Error = errno;
> + } else if (nread > 0) {
> + int i;
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + for (i = nread - 1; i >= 0; i--) {
> + IncompleteBytes = MR_list_cons(buffer[i], IncompleteBytes);
> + }
> + Error = 0;
> + } else {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + Error = 0;
> + }
> + } else {
> + Result = ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + #if defined(MR_BIG_ENDIAN)
> + ((unsigned char *) &UInt64)[0] = buffer[7];
> + ((unsigned char *) &UInt64)[1] = buffer[6];
> + ((unsigned char *) &UInt64)[2] = buffer[5];
> + ((unsigned char *) &UInt64)[3] = buffer[3];
> + ((unsigned char *) &UInt64)[4] = buffer[3];
> + ((unsigned char *) &UInt64)[5] = buffer[2];
> + ((unsigned char *) &UInt64)[6] = buffer[1];
> + ((unsigned char *) &UInt64)[7] = buffer[0];
> + #else
> + UInt64 = *((uint64_t *) buffer);
> + #endif
> + Error = 0;
> + }
> +").
> +
> +:- pragma foreign_proc("C#",
> + do_read_binary_uint64_le(Stream::in, Result::out, UInt64::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe],
> +"
> + byte[] buffer = new byte[8];
> + io.MR_MercuryFileStruct mf = Stream;
> + UInt64 = 0;
> + IncompleteBytes = list.empty_list();
> +
> + int nread = 0;
> +
> + if (mf.putback != -1) {
> + buffer[nread] = (byte) mf.putback;
> + nread++;
> + mf.putback = -1;
> + }
> +
> + try {
> + for ( ; nread < 8; nread++) {
> + int b = mf.stream.ReadByte();
> + if (b == -1) {
> + break;
> + }
> + buffer[nread] = (byte) b;
> + }
> + if (nread < 8) {
> + if (nread > 0) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + for (int i = nread - 1; i >=0; i--) {
> + IncompleteBytes = list.cons(buffer[i], IncompleteBytes);
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + UInt64 = (ulong) (
> + (ulong) buffer[7] << 56 |
> + (ulong) buffer[6] << 48 |
> + (ulong) buffer[5] << 40 |
> + (ulong) buffer[4] << 32 |
> + (ulong) buffer[3] << 24 |
> + (ulong) buffer[2] << 16 |
> + (ulong) buffer[1] << 8 |
> + (ulong) buffer[0]);
> + }
> + Error = null;
> + } catch (System.Exception e) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR;
> + Error = e;
> + }
> +").
> +
> +:- pragma foreign_proc("Java",
> + do_read_binary_uint64_le(Stream::in, Result::out, UInt64::out,
> + IncompleteBytes::out, Error::out, _IO0::di, _IO::uo),
> + [will_not_call_mercury, promise_pure, thread_safe],
> +"
> + byte[] buffer = new byte[8];
> + MR_BinaryInputFile mf = (MR_BinaryInputFile) Stream;
> + UInt64 = 0;
> + IncompleteBytes = list.empty_list();
> +
> + try {
> + int nread;
> + for (nread = 0; nread < 8; nread++) {
> + int next = mf.read_byte();
> + if (next == -1) {
> + break;
> + }
> + buffer[nread] = (byte) next;
> + }
> + if (nread < 8) {
> + if (nread > 0) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_INCOMPLETE;
> + for (int i = nread - 1; i >= 0; i--) {
> + IncompleteBytes = list.cons(buffer[i], IncompleteBytes);
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_EOF;
> + }
> + } else {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_OK;
> + UInt64 =
> + (long) (buffer[7] & 0xff) << 56 |
> + (long) (buffer[6] & 0xff) << 48 |
> + (long) (buffer[5] & 0xff) << 40 |
> + (long) (buffer[4] & 0xff) << 32 |
> + (long) (buffer[3] & 0xff) << 24 |
> + (long) (buffer[2] & 0xff) << 16 |
> + (long) (buffer[1] & 0xff) << 8 |
> + (long) (buffer[0] & 0xff);
> + }
> + Error = null;
> + } catch (java.lang.Exception e) {
> + Result = io.ML_MAYBE_INCOMPLETE_RESULT_CODE_ERROR;
> + Error = e;
> + }
> +").
> +
> +do_read_binary_uint64_le(_, _, _, _, _, _, _) :-
> + sorry($module, "do_read_binary_uint64_le NYI for Erlang").
> +
> +%---------------------%
> +
> +read_binary_uint64_be(Result, !IO) :-
> + binary_input_stream(Stream, !IO),
> + read_binary_uint64_be(Stream, Result, !IO).
> +
> +read_binary_uint64_be(binary_input_stream(Stream), Result, !IO) :-
> + do_read_binary_uint64_le(Stream, Result0, UInt64LE, IncompleteBytes,
> + Error, !IO),
> + (
> + Result0 = ok,
> + UInt64BE = uint64.reverse_bytes(UInt64LE),
> + Result = ok(UInt64BE)
> + ;
> + Result0 = eof,
> + Result = eof
> + ;
> + Result0 = incomplete,
> + Result = incomplete(IncompleteBytes)
> + ;
> + Result0 = error,
> + make_err_msg(Error, "read failed: ", Msg),
> + Result = error(io_error(Msg))
> + ).
> +
> +%---------------------%
> +
> read_bitmap(!Bitmap, BytesRead, Result, !IO) :-
> binary_input_stream(Stream, !IO),
> read_bitmap(Stream, !Bitmap, BytesRead, Result, !IO).
> diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
> index 78f7ef5..d99efb8 100644
> --- a/tests/hard_coded/Mmakefile
> +++ b/tests/hard_coded/Mmakefile
> @@ -303,6 +303,12 @@ ORDINARY_PROGS = \
> random_permutation \
> random_simple \
> rational_test \
> + read_binary_int16 \
> + read_binary_int32 \
> + read_binary_int64 \
> + read_binary_uint16 \
> + read_binary_uint32 \
> + read_binary_uint64 \
> read_min_int \
> recursive_main \
> redoip_clobber \
> diff --git a/tests/hard_coded/read_binary_int16.exp
> b/tests/hard_coded/read_binary_int16.exp
> index e69de29..c54276a 100644
> --- a/tests/hard_coded/read_binary_int16.exp
> +++ b/tests/hard_coded/read_binary_int16.exp
> @@ -0,0 +1,36 @@
> +================
> +Input: []
> +Result: EOF (read big-endian)
> +================
> +Input: [0u8]
> +Result: Incomplete ([0u8]) (read big-endian)
> +================
> +Input: [1u8, 0u8] (LE: 1) (BE: 256)
> +Result: 256i16 (read big-endian)
> +================
> +Input: [255u8, 0u8] (LE: 255) (BE: -256)
> +Result: -256i16 (read big-endian)
> +================
> +Input: []
> +Result: EOF (read little-endian)
> +================
> +Input: [0u8]
> +Result: Incomplete ([0u8]) (read little-endian)
> +================
> +Input: [1u8, 0u8] (LE: 1) (BE: 256)
> +Result: 1i16 (read little-endian)
> +================
> +Input: [255u8, 0u8] (LE: 255) (BE: -256)
> +Result: 255i16 (read little-endian)
> +================
> +Input: []
> +Result: EOF (read native byte order)
> +================
> +Input: [0u8]
> +Result: Incomplete ([0u8]) (read native byte order)
> +================
> +Input: [1u8, 0u8] (LE: 1) (BE: 256)
> +Result: 1i16 (read native byte order)
> +================
> +Input: [255u8, 0u8] (LE: 255) (BE: -256)
> +Result: 255i16 (read native byte order)
> diff --git a/tests/hard_coded/read_binary_int16.m
> b/tests/hard_coded/read_binary_int16.m
> index e69de29..171475b 100644
> --- a/tests/hard_coded/read_binary_int16.m
> +++ b/tests/hard_coded/read_binary_int16.m
> @@ -0,0 +1,143 @@
> +%---------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%---------------------------------------------------------------------------%
> +%
> +% Test reading of binary int16s.
> +%
> +%---------------------------------------------------------------------------%
> +
> +:- module read_binary_int16.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +%---------------------------------------------------------------------------%
> +%---------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module list.
> +:- import_module string.
> +:- import_module int16.
> +
> +%---------------------------------------------------------------------------%
> +
> +main(!IO) :-
> + list.foldl(run_test(big_endian), test_cases, !IO),
> + list.foldl(run_test(little_endian), test_cases, !IO),
> + list.foldl(run_test(native), test_cases, !IO).
> +
> +:- pred run_test(byte_order::in, test_case::in, io::di, io::uo) is det.
> +
> +run_test(ByteOrder, TestBytes, !IO) :-
> + io.remove_file(test_file, _, !IO),
> + io.write_string("================\n", !IO),
> + io.open_binary_output(test_file, OpenOutResult, !IO),
> + (
> + OpenOutResult = ok(OutFile),
> + io.write_string("Input: ", !IO),
> + io.write(TestBytes, !IO),
> + (
> + ( TestBytes = []
> + ; TestBytes = [_]
> + ; TestBytes = [_, _, _ | _]
> + ),
> + io.nl(!IO)
> + ;
> + TestBytes = [Byte1, Byte2],
> + io.write_string(" (LE: ", !IO),
> + io.write_int16(from_bytes_le(Byte1, Byte2), !IO),
> + io.write_string(") (BE: ", !IO),
> + io.write_int16(from_bytes_be(Byte1, Byte2), !IO),
> + io.write_string(")\n", !IO)
> + ),
> + list.foldl(write_binary_uint8(OutFile), TestBytes, !IO),
> + io.close_binary_output(OutFile, !IO),
> + io.open_binary_input(test_file, OpenInResult, !IO),
> + (
> + OpenInResult = ok(InFile),
> + (
> + ByteOrder = big_endian,
> + read_binary_int16_be(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = little_endian,
> + read_binary_int16_le(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = native,
> + read_binary_int16(InFile, ReadResult, !IO)
> + ),
> + (
> + ReadResult = ok(ResultUInt16),
> + io.write_string("Result: ", !IO),
> + io.write(ResultUInt16, !IO),
> + io.write_string(" (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = eof,
> + io.write_string("Result: EOF (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = incomplete(Bytes),
> + io.format("Result: Incomplete (%s) (", [s(string(Bytes))],
> + !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = error(IO_Error),
> + io.format("Result: Error (%s)\n",
> [s(io.error_message(IO_Error))],
> + !IO)
> + ),
> + io.remove_file(test_file, _, !IO)
> + ;
> + OpenInResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))],
> + !IO)
> + )
> + ;
> + OpenOutResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))], !IO)
> + ).
> +
> +:- pred describe_byte_order(byte_order::in, io::di, io::uo) is det.
> +
> +describe_byte_order(ByteOrder, !IO) :-
> + (
> + ByteOrder = big_endian,
> + io.write_string("read big-endian", !IO)
> + ;
> + ByteOrder = little_endian,
> + io.write_string("read little-endian", !IO)
> + ;
> + ByteOrder = native,
> + io.write_string("read native byte order", !IO)
> + ).
> +
> +:- func test_file = string.
> +
> +test_file = "read_binary_int16.bin".
> +
> +%---------------------------------------------------------------------------%
> +
> +:- type byte_order
> + ---> big_endian
> + ; little_endian
> + ; native.
> +
> +:- type test_case == list(uint8).
> +
> +:- func test_cases = list(test_case).
> +
> +test_cases = [
> + [],
> + [0u8],
> + [1u8, 0u8],
> + [0xffu8, 0u8]
> +].
> +
> +%---------------------------------------------------------------------------%
> +:- end_module read_binary_int16.
> +%---------------------------------------------------------------------------%
> diff --git a/tests/hard_coded/read_binary_int32.exp
> b/tests/hard_coded/read_binary_int32.exp
> index e69de29..26cf1b9 100644
> --- a/tests/hard_coded/read_binary_int32.exp
> +++ b/tests/hard_coded/read_binary_int32.exp
> @@ -0,0 +1,63 @@
> +================
> +Input: []
> +Result: EOF (read big-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read big-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 1u8] (LE: 16777216) (BE: 1)
> +Result: 1i32 (read big-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8] (LE: 255) (BE: -16777216)
> +Result: -16777216i32 (read big-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8] (LE: 257) (BE: 16842752)
> +Result: 16842752i32 (read big-endian)
> +================
> +Input: []
> +Result: EOF (read little-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read little-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 1u8] (LE: 16777216) (BE: 1)
> +Result: 16777216i32 (read little-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8] (LE: 255) (BE: -16777216)
> +Result: 255i32 (read little-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8] (LE: 257) (BE: 16842752)
> +Result: 257i32 (read little-endian)
> +================
> +Input: []
> +Result: EOF (read native byte order)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read native byte order)
> +================
> +Input: [0u8, 0u8, 0u8, 1u8] (LE: 16777216) (BE: 1)
> +Result: 16777216i32 (read native byte order)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8] (LE: 255) (BE: -16777216)
> +Result: 255i32 (read native byte order)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8] (LE: 257) (BE: 16842752)
> +Result: 257i32 (read native byte order)
> diff --git a/tests/hard_coded/read_binary_int32.m
> b/tests/hard_coded/read_binary_int32.m
> index e69de29..cecad92 100644
> --- a/tests/hard_coded/read_binary_int32.m
> +++ b/tests/hard_coded/read_binary_int32.m
> @@ -0,0 +1,141 @@
> +%---------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%---------------------------------------------------------------------------%
> +%
> +% Test reading of binary int32s.
> +%
> +%---------------------------------------------------------------------------%
> +
> +:- module read_binary_int32.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +%---------------------------------------------------------------------------%
> +%---------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module list.
> +:- import_module string.
> +:- import_module int32.
> +
> +%---------------------------------------------------------------------------%
> +
> +main(!IO) :-
> + list.foldl(run_test(big_endian), test_cases, !IO),
> + list.foldl(run_test(little_endian), test_cases, !IO),
> + list.foldl(run_test(native), test_cases, !IO).
> +
> +:- pred run_test(byte_order::in, test_case::in, io::di, io::uo) is det.
> +
> +run_test(ByteOrder, TestBytes, !IO) :-
> + io.remove_file(test_file, _, !IO),
> + io.write_string("================\n", !IO),
> + io.open_binary_output(test_file, OpenOutResult, !IO),
> + (
> + OpenOutResult = ok(OutFile),
> + io.write_string("Input: ", !IO),
> + io.write(TestBytes, !IO),
> + ( if TestBytes = [Byte1, Byte2, Byte3, Byte4] then
> + io.write_string(" (LE: ", !IO),
> + io.write_int32(from_bytes_le(Byte1, Byte2, Byte3, Byte4), !IO),
> + io.write_string(") (BE: ", !IO),
> + io.write_int32(from_bytes_be(Byte1, Byte2, Byte3, Byte4), !IO),
> + io.write_string(")\n", !IO)
> + else
> + io.nl(!IO)
> + ),
> + list.foldl(write_binary_uint8(OutFile), TestBytes, !IO),
> + io.close_binary_output(OutFile, !IO),
> + io.open_binary_input(test_file, OpenInResult, !IO),
> + (
> + OpenInResult = ok(InFile),
> + (
> + ByteOrder = big_endian,
> + read_binary_int32_be(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = little_endian,
> + read_binary_int32_le(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = native,
> + read_binary_int32(InFile, ReadResult, !IO)
> + ),
> + (
> + ReadResult = ok(ResultUInt16),
> + io.write_string("Result: ", !IO),
> + io.write(ResultUInt16, !IO),
> + io.write_string(" (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = eof,
> + io.write_string("Result: EOF (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = incomplete(Bytes),
> + io.format("Result: Incomplete (%s) (", [s(string(Bytes))],
> + !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = error(IO_Error),
> + io.format("Result: Error (%s)\n",
> [s(io.error_message(IO_Error))],
> + !IO)
> + ),
> + io.remove_file(test_file, _, !IO)
> + ;
> + OpenInResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))],
> + !IO)
> + )
> + ;
> + OpenOutResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))], !IO)
> + ).
> +
> +:- pred describe_byte_order(byte_order::in, io::di, io::uo) is det.
> +
> +describe_byte_order(ByteOrder, !IO) :-
> + (
> + ByteOrder = big_endian,
> + io.write_string("read big-endian", !IO)
> + ;
> + ByteOrder = little_endian,
> + io.write_string("read little-endian", !IO)
> + ;
> + ByteOrder = native,
> + io.write_string("read native byte order", !IO)
> + ).
> +
> +:- func test_file = string.
> +
> +test_file = "read_binary_int32.bin".
> +
> +%---------------------------------------------------------------------------%
> +
> +:- type byte_order
> + ---> big_endian
> + ; little_endian
> + ; native.
> +
> +:- type test_case == list(uint8).
> +
> +:- func test_cases = list(test_case).
> +
> +test_cases = [
> + [],
> + [1u8],
> + [1u8, 2u8],
> + [1u8, 2u8, 3u8],
> + [0u8, 0u8, 0u8, 1u8],
> + [0xffu8, 0u8, 0u8, 0u8],
> + [1u8, 1u8, 0u8, 0u8]
> +].
> +
> +%---------------------------------------------------------------------------%
> +:- end_module read_binary_int32.
> +%---------------------------------------------------------------------------%
> diff --git a/tests/hard_coded/read_binary_int64.exp
> b/tests/hard_coded/read_binary_int64.exp
> index e69de29..e975eab 100644
> --- a/tests/hard_coded/read_binary_int64.exp
> +++ b/tests/hard_coded/read_binary_int64.exp
> @@ -0,0 +1,108 @@
> +================
> +Input: []
> +Result: EOF (read big-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 6u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]) (read big-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8] (LE: 72057594037927936) (BE:
> 1)
> +Result: 1i64 (read big-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 255) (BE:
> -72057594037927936)
> +Result: -72057594037927936i64 (read big-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 257) (BE:
> 72339069014638592)
> +Result: 72339069014638592i64 (read big-endian)
> +================
> +Input: []
> +Result: EOF (read little-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 6u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]) (read
> little-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8] (LE: 72057594037927936) (BE:
> 1)
> +Result: 72057594037927936i64 (read little-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 255) (BE:
> -72057594037927936)
> +Result: 255i64 (read little-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 257) (BE:
> 72339069014638592)
> +Result: 257i64 (read little-endian)
> +================
> +Input: []
> +Result: EOF (read native byte order)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 6u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]) (read native byte
> order)
> +================
> +Input: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8] (LE: 72057594037927936) (BE:
> 1)
> +Result: 72057594037927936i64 (read native byte order)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 255) (BE:
> -72057594037927936)
> +Result: 255i64 (read native byte order)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 257) (BE:
> 72339069014638592)
> +Result: 257i64 (read native byte order)
> diff --git a/tests/hard_coded/read_binary_int64.m
> b/tests/hard_coded/read_binary_int64.m
> index e69de29..fdeb287 100644
> --- a/tests/hard_coded/read_binary_int64.m
> +++ b/tests/hard_coded/read_binary_int64.m
> @@ -0,0 +1,148 @@
> +%---------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%---------------------------------------------------------------------------%
> +%
> +% Test reading of binary int64s.
> +%
> +%---------------------------------------------------------------------------%
> +
> +:- module read_binary_int64.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +%---------------------------------------------------------------------------%
> +%---------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module list.
> +:- import_module string.
> +:- import_module int64.
> +
> +%---------------------------------------------------------------------------%
> +
> +main(!IO) :-
> + list.foldl(run_test(big_endian), test_cases, !IO),
> + list.foldl(run_test(little_endian), test_cases, !IO),
> + list.foldl(run_test(native), test_cases, !IO).
> +
> +:- pred run_test(byte_order::in, test_case::in, io::di, io::uo) is det.
> +
> +run_test(ByteOrder, TestBytes, !IO) :-
> + io.remove_file(test_file, _, !IO),
> + io.write_string("================\n", !IO),
> + io.open_binary_output(test_file, OpenOutResult, !IO),
> + (
> + OpenOutResult = ok(OutFile),
> + io.write_string("Input: ", !IO),
> + io.write(TestBytes, !IO),
> + ( if
> + TestBytes = [Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7,
> Byte8]
> + then
> + io.write_string(" (LE: ", !IO),
> + io.write_int64(from_bytes_le(Byte1, Byte2, Byte3, Byte4, Byte5,
> Byte6, Byte7, Byte8), !IO),
> + io.write_string(") (BE: ", !IO),
> + io.write_int64(from_bytes_be(Byte1, Byte2, Byte3, Byte4, Byte5,
> Byte6, Byte7, Byte8), !IO),
> + io.write_string(")\n", !IO)
> + else
> + io.nl(!IO)
> + ),
> + list.foldl(write_binary_uint8(OutFile), TestBytes, !IO),
> + io.close_binary_output(OutFile, !IO),
> + io.open_binary_input(test_file, OpenInResult, !IO),
> + (
> + OpenInResult = ok(InFile),
> + (
> + ByteOrder = big_endian,
> + read_binary_int64_be(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = little_endian,
> + read_binary_int64_le(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = native,
> + read_binary_int64(InFile, ReadResult, !IO)
> + ),
> + (
> + ReadResult = ok(ResultUInt16),
> + io.write_string("Result: ", !IO),
> + io.write(ResultUInt16, !IO),
> + io.write_string(" (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = eof,
> + io.write_string("Result: EOF (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = incomplete(Bytes),
> + io.format("Result: Incomplete (%s) (", [s(string(Bytes))],
> + !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = error(IO_Error),
> + io.format("Result: Error (%s)\n",
> [s(io.error_message(IO_Error))],
> + !IO)
> + ),
> + io.remove_file(test_file, _, !IO)
> + ;
> + OpenInResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))],
> + !IO)
> + )
> + ;
> + OpenOutResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))], !IO)
> + ).
> +
> +:- pred describe_byte_order(byte_order::in, io::di, io::uo) is det.
> +
> +describe_byte_order(ByteOrder, !IO) :-
> + (
> + ByteOrder = big_endian,
> + io.write_string("read big-endian", !IO)
> + ;
> + ByteOrder = little_endian,
> + io.write_string("read little-endian", !IO)
> + ;
> + ByteOrder = native,
> + io.write_string("read native byte order", !IO)
> + ).
> +
> +:- func test_file = string.
> +
> +test_file = "read_binary_int64.bin".
> +
> +%---------------------------------------------------------------------------%
> +
> +:- type byte_order
> + ---> big_endian
> + ; little_endian
> + ; native.
> +
> +:- type test_case == list(uint8).
> +
> +:- func test_cases = list(test_case).
> +
> +test_cases = [
> + [],
> + [1u8],
> + [1u8, 2u8],
> + [1u8, 2u8, 3u8],
> + [1u8, 2u8, 3u8, 4u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8, 6u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8, 7u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8],
> + [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8],
> + [0xffu8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8],
> + [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]
> +].
> +
> +%---------------------------------------------------------------------------%
> +:- end_module read_binary_int64.
> +%---------------------------------------------------------------------------%
> diff --git a/tests/hard_coded/read_binary_uint16.exp
> b/tests/hard_coded/read_binary_uint16.exp
> index e69de29..658cef5 100644
> --- a/tests/hard_coded/read_binary_uint16.exp
> +++ b/tests/hard_coded/read_binary_uint16.exp
> @@ -0,0 +1,36 @@
> +================
> +Input: []
> +Result: EOF (read big-endian)
> +================
> +Input: [0u8]
> +Result: Incomplete ([0u8]) (read big-endian)
> +================
> +Input: [1u8, 0u8] (LE: 1) (BE: 256)
> +Result: 256u16 (read big-endian)
> +================
> +Input: [255u8, 0u8] (LE: 255) (BE: 65280)
> +Result: 65280u16 (read big-endian)
> +================
> +Input: []
> +Result: EOF (read little-endian)
> +================
> +Input: [0u8]
> +Result: Incomplete ([0u8]) (read little-endian)
> +================
> +Input: [1u8, 0u8] (LE: 1) (BE: 256)
> +Result: 1u16 (read little-endian)
> +================
> +Input: [255u8, 0u8] (LE: 255) (BE: 65280)
> +Result: 255u16 (read little-endian)
> +================
> +Input: []
> +Result: EOF (read native byte order)
> +================
> +Input: [0u8]
> +Result: Incomplete ([0u8]) (read native byte order)
> +================
> +Input: [1u8, 0u8] (LE: 1) (BE: 256)
> +Result: 1u16 (read native byte order)
> +================
> +Input: [255u8, 0u8] (LE: 255) (BE: 65280)
> +Result: 255u16 (read native byte order)
> diff --git a/tests/hard_coded/read_binary_uint16.m
> b/tests/hard_coded/read_binary_uint16.m
> index e69de29..8a0ec6e 100644
> --- a/tests/hard_coded/read_binary_uint16.m
> +++ b/tests/hard_coded/read_binary_uint16.m
> @@ -0,0 +1,143 @@
> +%---------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%---------------------------------------------------------------------------%
> +%
> +% Test reading of binary uint16s.
> +%
> +%---------------------------------------------------------------------------%
> +
> +:- module read_binary_uint16.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +%---------------------------------------------------------------------------%
> +%---------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module list.
> +:- import_module string.
> +:- import_module uint16.
> +
> +%---------------------------------------------------------------------------%
> +
> +main(!IO) :-
> + list.foldl(run_test(big_endian), test_cases, !IO),
> + list.foldl(run_test(little_endian), test_cases, !IO),
> + list.foldl(run_test(native), test_cases, !IO).
> +
> +:- pred run_test(byte_order::in, test_case::in, io::di, io::uo) is det.
> +
> +run_test(ByteOrder, TestBytes, !IO) :-
> + io.remove_file(test_file, _, !IO),
> + io.write_string("================\n", !IO),
> + io.open_binary_output(test_file, OpenOutResult, !IO),
> + (
> + OpenOutResult = ok(OutFile),
> + io.write_string("Input: ", !IO),
> + io.write(TestBytes, !IO),
> + (
> + ( TestBytes = []
> + ; TestBytes = [_]
> + ; TestBytes = [_, _, _ | _]
> + ),
> + io.nl(!IO)
> + ;
> + TestBytes = [Byte1, Byte2],
> + io.write_string(" (LE: ", !IO),
> + io.write_uint16(from_bytes_le(Byte1, Byte2), !IO),
> + io.write_string(") (BE: ", !IO),
> + io.write_uint16(from_bytes_be(Byte1, Byte2), !IO),
> + io.write_string(")\n", !IO)
> + ),
> + list.foldl(write_binary_uint8(OutFile), TestBytes, !IO),
> + io.close_binary_output(OutFile, !IO),
> + io.open_binary_input(test_file, OpenInResult, !IO),
> + (
> + OpenInResult = ok(InFile),
> + (
> + ByteOrder = big_endian,
> + read_binary_uint16_be(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = little_endian,
> + read_binary_uint16_le(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = native,
> + read_binary_uint16(InFile, ReadResult, !IO)
> + ),
> + (
> + ReadResult = ok(ResultUInt16),
> + io.write_string("Result: ", !IO),
> + io.write(ResultUInt16, !IO),
> + io.write_string(" (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = eof,
> + io.write_string("Result: EOF (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = incomplete(Bytes),
> + io.format("Result: Incomplete (%s) (", [s(string(Bytes))],
> + !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = error(IO_Error),
> + io.format("Result: Error (%s)\n",
> [s(io.error_message(IO_Error))],
> + !IO)
> + ),
> + io.remove_file(test_file, _, !IO)
> + ;
> + OpenInResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))],
> + !IO)
> + )
> + ;
> + OpenOutResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))], !IO)
> + ).
> +
> +:- pred describe_byte_order(byte_order::in, io::di, io::uo) is det.
> +
> +describe_byte_order(ByteOrder, !IO) :-
> + (
> + ByteOrder = big_endian,
> + io.write_string("read big-endian", !IO)
> + ;
> + ByteOrder = little_endian,
> + io.write_string("read little-endian", !IO)
> + ;
> + ByteOrder = native,
> + io.write_string("read native byte order", !IO)
> + ).
> +
> +:- func test_file = string.
> +
> +test_file = "read_binary_uint16.bin".
> +
> +%---------------------------------------------------------------------------%
> +
> +:- type byte_order
> + ---> big_endian
> + ; little_endian
> + ; native.
> +
> +:- type test_case == list(uint8).
> +
> +:- func test_cases = list(test_case).
> +
> +test_cases = [
> + [],
> + [0u8],
> + [1u8, 0u8],
> + [0xffu8, 0u8]
> +].
> +
> +%---------------------------------------------------------------------------%
> +:- end_module read_binary_uint16.
> +%---------------------------------------------------------------------------%
> diff --git a/tests/hard_coded/read_binary_uint32.exp
> b/tests/hard_coded/read_binary_uint32.exp
> index e69de29..7225201 100644
> --- a/tests/hard_coded/read_binary_uint32.exp
> +++ b/tests/hard_coded/read_binary_uint32.exp
> @@ -0,0 +1,63 @@
> +================
> +Input: []
> +Result: EOF (read big-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read big-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 1u8] (LE: 16777216) (BE: 1)
> +Result: 1u32 (read big-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8] (LE: 255) (BE: 4278190080)
> +Result: 4278190080u32 (read big-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8] (LE: 257) (BE: 16842752)
> +Result: 16842752u32 (read big-endian)
> +================
> +Input: []
> +Result: EOF (read little-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read little-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 1u8] (LE: 16777216) (BE: 1)
> +Result: 16777216u32 (read little-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8] (LE: 255) (BE: 4278190080)
> +Result: 255u32 (read little-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8] (LE: 257) (BE: 16842752)
> +Result: 257u32 (read little-endian)
> +================
> +Input: []
> +Result: EOF (read native byte order)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read native byte order)
> +================
> +Input: [0u8, 0u8, 0u8, 1u8] (LE: 16777216) (BE: 1)
> +Result: 16777216u32 (read native byte order)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8] (LE: 255) (BE: 4278190080)
> +Result: 255u32 (read native byte order)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8] (LE: 257) (BE: 16842752)
> +Result: 257u32 (read native byte order)
> diff --git a/tests/hard_coded/read_binary_uint32.m
> b/tests/hard_coded/read_binary_uint32.m
> index e69de29..c400c12 100644
> --- a/tests/hard_coded/read_binary_uint32.m
> +++ b/tests/hard_coded/read_binary_uint32.m
> @@ -0,0 +1,141 @@
> +%---------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%---------------------------------------------------------------------------%
> +%
> +% Test reading of binary uint32s.
> +%
> +%---------------------------------------------------------------------------%
> +
> +:- module read_binary_uint32.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +%---------------------------------------------------------------------------%
> +%---------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module list.
> +:- import_module string.
> +:- import_module uint32.
> +
> +%---------------------------------------------------------------------------%
> +
> +main(!IO) :-
> + list.foldl(run_test(big_endian), test_cases, !IO),
> + list.foldl(run_test(little_endian), test_cases, !IO),
> + list.foldl(run_test(native), test_cases, !IO).
> +
> +:- pred run_test(byte_order::in, test_case::in, io::di, io::uo) is det.
> +
> +run_test(ByteOrder, TestBytes, !IO) :-
> + io.remove_file(test_file, _, !IO),
> + io.write_string("================\n", !IO),
> + io.open_binary_output(test_file, OpenOutResult, !IO),
> + (
> + OpenOutResult = ok(OutFile),
> + io.write_string("Input: ", !IO),
> + io.write(TestBytes, !IO),
> + ( if TestBytes = [Byte1, Byte2, Byte3, Byte4] then
> + io.write_string(" (LE: ", !IO),
> + io.write_uint32(from_bytes_le(Byte1, Byte2, Byte3, Byte4), !IO),
> + io.write_string(") (BE: ", !IO),
> + io.write_uint32(from_bytes_be(Byte1, Byte2, Byte3, Byte4), !IO),
> + io.write_string(")\n", !IO)
> + else
> + io.nl(!IO)
> + ),
> + list.foldl(write_binary_uint8(OutFile), TestBytes, !IO),
> + io.close_binary_output(OutFile, !IO),
> + io.open_binary_input(test_file, OpenInResult, !IO),
> + (
> + OpenInResult = ok(InFile),
> + (
> + ByteOrder = big_endian,
> + read_binary_uint32_be(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = little_endian,
> + read_binary_uint32_le(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = native,
> + read_binary_uint32(InFile, ReadResult, !IO)
> + ),
> + (
> + ReadResult = ok(ResultUInt16),
> + io.write_string("Result: ", !IO),
> + io.write(ResultUInt16, !IO),
> + io.write_string(" (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = eof,
> + io.write_string("Result: EOF (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = incomplete(Bytes),
> + io.format("Result: Incomplete (%s) (", [s(string(Bytes))],
> + !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = error(IO_Error),
> + io.format("Result: Error (%s)\n",
> [s(io.error_message(IO_Error))],
> + !IO)
> + ),
> + io.remove_file(test_file, _, !IO)
> + ;
> + OpenInResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))],
> + !IO)
> + )
> + ;
> + OpenOutResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))], !IO)
> + ).
> +
> +:- pred describe_byte_order(byte_order::in, io::di, io::uo) is det.
> +
> +describe_byte_order(ByteOrder, !IO) :-
> + (
> + ByteOrder = big_endian,
> + io.write_string("read big-endian", !IO)
> + ;
> + ByteOrder = little_endian,
> + io.write_string("read little-endian", !IO)
> + ;
> + ByteOrder = native,
> + io.write_string("read native byte order", !IO)
> + ).
> +
> +:- func test_file = string.
> +
> +test_file = "read_binary_uint32.bin".
> +
> +%---------------------------------------------------------------------------%
> +
> +:- type byte_order
> + ---> big_endian
> + ; little_endian
> + ; native.
> +
> +:- type test_case == list(uint8).
> +
> +:- func test_cases = list(test_case).
> +
> +test_cases = [
> + [],
> + [1u8],
> + [1u8, 2u8],
> + [1u8, 2u8, 3u8],
> + [0u8, 0u8, 0u8, 1u8],
> + [0xffu8, 0u8, 0u8, 0u8],
> + [1u8, 1u8, 0u8, 0u8]
> +].
> +
> +%---------------------------------------------------------------------------%
> +:- end_module read_binary_uint32.
> +%---------------------------------------------------------------------------%
> diff --git a/tests/hard_coded/read_binary_uint64.exp
> b/tests/hard_coded/read_binary_uint64.exp
> index e69de29..6144024 100644
> --- a/tests/hard_coded/read_binary_uint64.exp
> +++ b/tests/hard_coded/read_binary_uint64.exp
> @@ -0,0 +1,108 @@
> +================
> +Input: []
> +Result: EOF (read big-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 6u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8]) (read big-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]) (read big-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8] (LE: 72057594037927936) (BE:
> 1)
> +Result: 1u64 (read big-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 255) (BE:
> 18374686479671623680)
> +Result: 18374686479671623680u64 (read big-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 257) (BE:
> 72339069014638592)
> +Result: 72339069014638592u64 (read big-endian)
> +================
> +Input: []
> +Result: EOF (read little-endian)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 6u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8]) (read little-endian)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]) (read
> little-endian)
> +================
> +Input: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8] (LE: 72057594037927936) (BE:
> 1)
> +Result: 72057594037927936u64 (read little-endian)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 255) (BE:
> 18374686479671623680)
> +Result: 255u64 (read little-endian)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 257) (BE:
> 72339069014638592)
> +Result: 257u64 (read little-endian)
> +================
> +Input: []
> +Result: EOF (read native byte order)
> +================
> +Input: [1u8]
> +Result: Incomplete ([1u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8]
> +Result: Incomplete ([1u8, 2u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8]
> +Result: Incomplete ([1u8, 2u8, 3u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 6u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 6u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8]) (read native byte order)
> +================
> +Input: [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]
> +Result: Incomplete ([1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8]) (read native byte
> order)
> +================
> +Input: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8] (LE: 72057594037927936) (BE:
> 1)
> +Result: 72057594037927936u64 (read native byte order)
> +================
> +Input: [255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 255) (BE:
> 18374686479671623680)
> +Result: 255u64 (read native byte order)
> +================
> +Input: [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] (LE: 257) (BE:
> 72339069014638592)
> +Result: 257u64 (read native byte order)
> diff --git a/tests/hard_coded/read_binary_uint64.m
> b/tests/hard_coded/read_binary_uint64.m
> index e69de29..165b5c9 100644
> --- a/tests/hard_coded/read_binary_uint64.m
> +++ b/tests/hard_coded/read_binary_uint64.m
> @@ -0,0 +1,148 @@
> +%---------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%---------------------------------------------------------------------------%
> +%
> +% Test reading of binary uint64s.
> +%
> +%---------------------------------------------------------------------------%
> +
> +:- module read_binary_uint64.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +%---------------------------------------------------------------------------%
> +%---------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module list.
> +:- import_module string.
> +:- import_module uint64.
> +
> +%---------------------------------------------------------------------------%
> +
> +main(!IO) :-
> + list.foldl(run_test(big_endian), test_cases, !IO),
> + list.foldl(run_test(little_endian), test_cases, !IO),
> + list.foldl(run_test(native), test_cases, !IO).
> +
> +:- pred run_test(byte_order::in, test_case::in, io::di, io::uo) is det.
> +
> +run_test(ByteOrder, TestBytes, !IO) :-
> + io.remove_file(test_file, _, !IO),
> + io.write_string("================\n", !IO),
> + io.open_binary_output(test_file, OpenOutResult, !IO),
> + (
> + OpenOutResult = ok(OutFile),
> + io.write_string("Input: ", !IO),
> + io.write(TestBytes, !IO),
> + ( if
> + TestBytes = [Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7,
> Byte8]
> + then
> + io.write_string(" (LE: ", !IO),
> + io.write_uint64(from_bytes_le(Byte1, Byte2, Byte3, Byte4, Byte5,
> Byte6, Byte7, Byte8), !IO),
> + io.write_string(") (BE: ", !IO),
> + io.write_uint64(from_bytes_be(Byte1, Byte2, Byte3, Byte4, Byte5,
> Byte6, Byte7, Byte8), !IO),
> + io.write_string(")\n", !IO)
> + else
> + io.nl(!IO)
> + ),
> + list.foldl(write_binary_uint8(OutFile), TestBytes, !IO),
> + io.close_binary_output(OutFile, !IO),
> + io.open_binary_input(test_file, OpenInResult, !IO),
> + (
> + OpenInResult = ok(InFile),
> + (
> + ByteOrder = big_endian,
> + read_binary_uint64_be(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = little_endian,
> + read_binary_uint64_le(InFile, ReadResult, !IO)
> + ;
> + ByteOrder = native,
> + read_binary_uint64(InFile, ReadResult, !IO)
> + ),
> + (
> + ReadResult = ok(ResultUInt16),
> + io.write_string("Result: ", !IO),
> + io.write(ResultUInt16, !IO),
> + io.write_string(" (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = eof,
> + io.write_string("Result: EOF (", !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = incomplete(Bytes),
> + io.format("Result: Incomplete (%s) (", [s(string(Bytes))],
> + !IO),
> + describe_byte_order(ByteOrder, !IO),
> + io.write_string(")\n", !IO)
> + ;
> + ReadResult = error(IO_Error),
> + io.format("Result: Error (%s)\n",
> [s(io.error_message(IO_Error))],
> + !IO)
> + ),
> + io.remove_file(test_file, _, !IO)
> + ;
> + OpenInResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))],
> + !IO)
> + )
> + ;
> + OpenOutResult = error(IO_Error),
> + io.format("I/O ERROR: %s\n", [s(io.error_message(IO_Error))], !IO)
> + ).
> +
> +:- pred describe_byte_order(byte_order::in, io::di, io::uo) is det.
> +
> +describe_byte_order(ByteOrder, !IO) :-
> + (
> + ByteOrder = big_endian,
> + io.write_string("read big-endian", !IO)
> + ;
> + ByteOrder = little_endian,
> + io.write_string("read little-endian", !IO)
> + ;
> + ByteOrder = native,
> + io.write_string("read native byte order", !IO)
> + ).
> +
> +:- func test_file = string.
> +
> +test_file = "read_binary_uint64.bin".
> +
> +%---------------------------------------------------------------------------%
> +
> +:- type byte_order
> + ---> big_endian
> + ; little_endian
> + ; native.
> +
> +:- type test_case == list(uint8).
> +
> +:- func test_cases = list(test_case).
> +
> +test_cases = [
> + [],
> + [1u8],
> + [1u8, 2u8],
> + [1u8, 2u8, 3u8],
> + [1u8, 2u8, 3u8, 4u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8, 6u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8, 7u8],
> + [1u8, 2u8, 3u8, 4u8, 5u8, 7u8, 8u8],
> + [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8],
> + [0xffu8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8],
> + [1u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]
> +].
> +
> +%---------------------------------------------------------------------------%
> +:- end_module read_binary_uint64.
> +%---------------------------------------------------------------------------%
>
>
More information about the reviews
mailing list