[m-rev.] for review: putback of 8-bit values to binary input streams

Julien Fischer jfischer at opturion.com
Fri Oct 5 12:36:11 AEST 2018


For review by anyone.

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

Putback of 8-bit values to binary input streams.

Support direct putback of int8 and uint8 values to binary input streams
instead of via the bottom 8 bits of an int value.

library/io.m:
     Add putback_{int8,uint8}/[34].

     Add stream type class instances for putback streams binary_input_stream
     with int8 and uint8.

tests/hard_coded/Mmakefile:
tests/hard_coded/putback_binary_int8.{m,exp}:
tests/hard_coded/putback_binary_uint8.{m,exp}:
     Add tests of the above.

Julien.

diff --git a/library/io.m b/library/io.m
index 20af25a..b3356ff 100644
--- a/library/io.m
+++ b/library/io.m
@@ -1014,6 +1014,20 @@
  :- pred putback_byte(io.binary_input_stream::in, int::in, io::di, io::uo)
      is det.

+    % As above, but un-reads an int8 instead of a byte represented by
+    % the bottom 8 bits of an int.
+    %
+:- pred putback_int8(int8::in, io::di, io::uo) is det.
+:- pred putback_int8(io.binary_input_stream::in, int8::in, io::di, io::uo)
+    is det.
+
+    % As above, but un-reads a uint8 instead of a byte represented by
+    % the bottom 8 bits of an int.
+    %
+:- pred putback_uint8(uint8::in, io::di, io::uo) is det.
+:- pred putback_uint8(io.binary_input_stream::in, uint8::in, io::di, io::uo)
+    is det.
+
  %---------------------------------------------------------------------------%
  %
  % Binary output predicates.
@@ -1753,6 +1767,8 @@
  :- instance stream.bulk_reader(binary_input_stream, int,
          bitmap, io, io.error).
  :- instance stream.putback(binary_input_stream, int, io, io.error).
+:- instance stream.putback(binary_input_stream, int8, io, io.error).
+:- instance stream.putback(binary_input_stream, uint8, io, io.error).
  :- instance stream.seekable(binary_input_stream, io).

  %---------------------------------------------------------------------------%
@@ -4480,6 +4496,14 @@ putback_byte(Char, !IO) :-
      binary_input_stream(Stream, !IO),
      putback_byte(Stream, Char, !IO).

+putback_int8(Int8, !IO) :-
+    binary_input_stream(Stream, !IO),
+    putback_int8(Stream, Int8, !IO).
+
+putback_uint8(UInt8, !IO) :-
+    binary_input_stream(Stream, !IO),
+    putback_uint8(Stream, UInt8, !IO).
+
  read(Result, !IO) :-
      term_io.read_term(ReadResult, !IO),
      get_line_number(LineNumber, !IO),
@@ -7747,6 +7771,39 @@ putback_byte(binary_input_stream(Stream), Character, !IO) :-
      }
  ").

+putback_int8(binary_input_stream(Stream), Int8, !IO) :-
+    UInt8 = uint8.cast_from_int8(Int8),
+    putback_uint8_2(Stream, UInt8, Ok, !IO),
+    (
+        Ok = yes
+    ;
+        Ok = no,
+        throw(io_error("failed to put back int8"))
+    ).
+
+putback_uint8(binary_input_stream(Stream), UInt8, !IO) :-
+    putback_uint8_2(Stream, UInt8, Ok, !IO),
+    (
+        Ok = yes
+    ;
+        Ok = no,
+        throw(io_error("failed to put back uint8"))
+    ).
+
+:- pred putback_uint8_2(stream::in, uint8::in, bool::out, io::di, io::uo) is det.
+:- pragma foreign_proc("C",
+    putback_uint8_2(Stream::in, UInt8::in, Ok::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io,
+        does_not_affect_liveness, no_sharing],
+"
+    MercuryFilePtr mf = Stream;
+    if (MR_UNGETCH(*mf, UInt8) == EOF) {
+        Ok = MR_FALSE;
+    } else {
+        Ok = MR_TRUE;
+    }
+").
+
  :- pragma foreign_proc("C#",
      read_char_code_2(File::in, Result::out, Char::out, Error::out,
          _IO0::di, _IO::uo),
@@ -7829,6 +7886,19 @@ putback_byte(binary_input_stream(Stream), Character, !IO) :-
      }
  ").

+:- pragma foreign_proc("C#",
+    putback_uint8_2(File::in, UInt8::in, Ok::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure],
+"
+    io.MR_MercuryFileStruct mf = File;
+    if (mf.putback == -1) {
+        mf.putback = UInt8;
+        Ok = mr_bool.YES;
+    } else {
+        Ok = mr_bool.NO;
+    }
+").
+
  :- pragma foreign_proc("Java",
      read_char_code_2(File::in, Result::out, CharCode::out, Error::out,
          _IO0::di, _IO::uo),
@@ -7889,6 +7959,14 @@ putback_byte(binary_input_stream(Stream), Character, !IO) :-
      Ok = bool.YES;
  ").

+:- pragma foreign_proc("Java",
+    putback_uint8_2(File::in, UInt8::in, Ok::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+    ((io.MR_BinaryInputFile) File).ungetc((byte) UInt8);
+    Ok = bool.YES;
+").
+
  :- pragma foreign_proc("Erlang",
      read_char_code_2(Stream::in, Result::out, Char::out, Error::out,
          _IO0::di, _IO::uo),
@@ -7949,6 +8027,14 @@ putback_byte(binary_input_stream(Stream), Character, !IO) :-
      Ok = {yes}
  ").

+:- pragma foreign_proc("Erlang",
+    putback_uint8_2(File::in, UInt8::in, Ok::out, _IO0::di, _IO::uo),
+    [will_not_call_mercury, promise_pure, tabled_for_io],
+"
+    mercury__io:mercury_putback(File, UInt8),
+    Ok = {yes}
+").
+
  %---------------------------------------------------------------------------%
  %
  % Output predicates (with output to mercury_current_text_output).
@@ -12636,6 +12722,18 @@ result_to_stream_result(error(Error)) = error(Error).
      pred(unget/4) is putback_byte
  ].

+:- instance stream.putback(binary_input_stream, int8, io, io.error)
+    where
+[
+    pred(unget/4) is putback_int8
+].
+
+:- instance stream.putback(binary_input_stream, uint8, io, io.error)
+    where
+[
+    pred(unget/4) is putback_uint8
+].
+
  :- instance stream.seekable(binary_input_stream, io)
      where
  [
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 7c6e8cb..619f71f 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -287,6 +287,8 @@ ORDINARY_PROGS = \
  	promise_eqv_solns_typeclasses \
  	psqueue_test \
  	pure_mutable \
+	putback_binary_int8 \
+	putback_binary_uint8 \
  	puzzle_detism_bug \
  	qual_adv_test \
  	qual_basic_test \
diff --git a/tests/hard_coded/putback_binary_int8.exp b/tests/hard_coded/putback_binary_int8.exp
index e69de29..5eeffc2 100644
--- a/tests/hard_coded/putback_binary_int8.exp
+++ b/tests/hard_coded/putback_binary_int8.exp
@@ -0,0 +1,32 @@
+Position: 0
+
+Read: 97i8
+Position: 1
+
+Seek: +1
+Position: 2
+
+Read: 99i8
+Position: 3
+
+Put back: -128i8
+Position: 2
+
+Read: -128i8
+Position: 3
+
+Read: 10i8
+Position: 4
+
+Read: eof
+Position: 4
+
+Put back: 127i8
+Position: 3
+
+Seek: -2
+Position: 1
+
+Read: 98i8
+Position: 2
+
diff --git a/tests/hard_coded/putback_binary_int8.m b/tests/hard_coded/putback_binary_int8.m
index e69de29..0fd5146 100644
--- a/tests/hard_coded/putback_binary_int8.m
+++ b/tests/hard_coded/putback_binary_int8.m
@@ -0,0 +1,88 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+%
+% Test putback for int8 values with binary streams.
+%
+%---------------------------------------------------------------------------%
+
+:- module putback_binary_int8.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module char.
+:- import_module int.
+:- import_module list.
+:- import_module require.
+:- import_module string.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+    io.open_binary_input("stream_putback.data", OpenRes, !IO),
+    (
+        OpenRes = ok(Stream),
+        print_position(Stream, !IO),         % pos 0
+        print_read_byte(Stream, !IO),        % pos 1
+        print_relseek(Stream, 1, !IO),       % pos 2
+        print_read_byte(Stream, !IO),        % pos 3
+        print_putback(Stream, -128i8, !IO),  % pos 2
+        print_read_byte(Stream, !IO),        % -128i8 pos 3
+        print_read_byte(Stream, !IO),        % 10i8 (\n), pos 4
+        print_read_byte(Stream, !IO),        % eof, pos 4
+        print_putback(Stream, 127i8, !IO),   % pos 3
+        print_relseek(Stream, -2, !IO),      % pos 1; pushback dropped
+        print_read_byte(Stream, !IO),        % b, pos 2
+        io.close_binary_input(Stream, !IO)
+    ;
+        OpenRes = error(Error),
+        error(io.error_message(Error))
+    ).
+
+:- pred print_read_byte(io.binary_input_stream::in, io::di, io::uo) is det.
+
+print_read_byte(Stream, !IO) :-
+    io.read_binary_int8(Stream, ReadRes, !IO),
+    (
+        ReadRes = ok(Int8),
+        io.write_string("Read: ", !IO),
+        io.write_line(Int8, !IO)
+    ;
+        ReadRes = eof,
+        io.write_string("Read: eof\n", !IO)
+    ;
+        ReadRes = error(Error),
+        error(io.error_message(Error))
+    ),
+    print_position(Stream, !IO).
+
+:- pred print_putback(io.binary_input_stream::in, int8::in, io::di, io::uo)
+    is det.
+
+print_putback(Stream, Int8, !IO) :-
+    io.putback_int8(Stream, Int8, !IO),
+    io.write_string("Put back: ", !IO),
+    io.write_line(Int8, !IO),
+    print_position(Stream, !IO).
+
+:- pred print_relseek(io.binary_input_stream::in, int::in, io::di, io::uo)
+    is det.
+
+print_relseek(Stream, Offset, !IO) :-
+    io.seek_binary_input(Stream, cur, Offset, !IO),
+    io.format("Seek: %+d\n", [i(Offset)], !IO),
+    print_position(Stream, !IO).
+
+:- pred print_position(io.binary_input_stream::in, io::di, io::uo) is det.
+
+print_position(Stream, !IO) :-
+    io.binary_input_stream_offset(Stream, Offset, !IO),
+    io.format("Position: %d\n\n", [i(Offset)], !IO).
diff --git a/tests/hard_coded/putback_binary_uint8.m b/tests/hard_coded/putback_binary_uint8.m
index e69de29..b6e2489 100644
--- a/tests/hard_coded/putback_binary_uint8.m
+++ b/tests/hard_coded/putback_binary_uint8.m
@@ -0,0 +1,88 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+%
+% Test putback for uint8 values with binary streams.
+%
+%---------------------------------------------------------------------------%
+
+:- module putback_binary_uint8.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module char.
+:- import_module int.
+:- import_module list.
+:- import_module require.
+:- import_module string.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+    io.open_binary_input("stream_putback.data", OpenRes, !IO),
+    (
+        OpenRes = ok(Stream),
+        print_position(Stream, !IO),        % pos 0
+        print_read_byte(Stream, !IO),       % pos 1
+        print_relseek(Stream, 1, !IO),      % pos 2
+        print_read_byte(Stream, !IO),       % pos 3
+        print_putback(Stream, 128u8, !IO),  % pos 2
+        print_read_byte(Stream, !IO),       % 128u8 pos 3
+        print_read_byte(Stream, !IO),       % 10u8 (\n), pos 4
+        print_read_byte(Stream, !IO),       % eof, pos 4
+        print_putback(Stream, 255u8, !IO),  % pos 3
+        print_relseek(Stream, -2, !IO),     % pos 1; pushback dropped
+        print_read_byte(Stream, !IO),       % b, pos 2
+        io.close_binary_input(Stream, !IO)
+    ;
+        OpenRes = error(Error),
+        error(io.error_message(Error))
+    ).
+
+:- pred print_read_byte(io.binary_input_stream::in, io::di, io::uo) is det.
+
+print_read_byte(Stream, !IO) :-
+    io.read_binary_uint8(Stream, ReadRes, !IO),
+    (
+        ReadRes = ok(UInt8),
+        io.write_string("Read: ", !IO),
+        io.write_line(UInt8, !IO)
+    ;
+        ReadRes = eof,
+        io.write_string("Read: eof\n", !IO)
+    ;
+        ReadRes = error(Error),
+        error(io.error_message(Error))
+    ),
+    print_position(Stream, !IO).
+
+:- pred print_putback(io.binary_input_stream::in, uint8::in, io::di, io::uo)
+    is det.
+
+print_putback(Stream, UInt8, !IO) :-
+    io.putback_uint8(Stream, UInt8, !IO),
+    io.write_string("Put back: ", !IO),
+    io.write_line(UInt8, !IO),
+    print_position(Stream, !IO).
+
+:- pred print_relseek(io.binary_input_stream::in, int::in, io::di, io::uo)
+    is det.
+
+print_relseek(Stream, Offset, !IO) :-
+    io.seek_binary_input(Stream, cur, Offset, !IO),
+    io.format("Seek: %+d\n", [i(Offset)], !IO),
+    print_position(Stream, !IO).
+
+:- pred print_position(io.binary_input_stream::in, io::di, io::uo) is det.
+
+print_position(Stream, !IO) :-
+    io.binary_input_stream_offset(Stream, Offset, !IO),
+    io.format("Position: %d\n\n", [i(Offset)], !IO).


More information about the reviews mailing list