Next: , Previous: bit_buffer, Up: Top


8 bit_buffer.read

     %--------------------------------------------------%
     % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
     %--------------------------------------------------%
     % Copyright (C) 2007, 2010-2011 The University of Melbourne
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     % File: bit_buffer.read.m.
     % Main author: stayl.
     % Stability: low.
     %
     % A bit buffer provides an interface between bit-oriented input requests
     % and byte-oriented streams, getting a large chunk of bits with one call
     % to `bulk_get', then satisfying bit-oriented requests from the buffer.
     %
     % Return values of `error(...)' are only used for errors in the stream
     % being read.  Once an error value has been returned, all future calls
     % will return that error.
     %
     % Bounds errors or invalid argument errors (for example a read request
     % for a negative number of bits) will result in an exception being thrown.
     % Requests triggering an exception in this way will not change the state
     % of the stream.
     %
     % CAVEAT: the user is referred to the documentation in the header
     % of array.m regarding programming with unique objects (the compiler
     % does not currently recognise them, hence we are forced to use
     % non-unique modes until the situation is rectified; this places
     % a small burden on the programmer to ensure the correctness of his
     % code that would otherwise be assured by the compiler.)
     %
     %--------------------------------------------------%
     %--------------------------------------------------%
     
     :- module bit_buffer.read.
     :- interface.
     
     :- import_module io.
     :- import_module bitmap.
     
     :- type read_buffer(Stream, State, Error).
             % <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     
     :- type read_buffer ==
                 read_buffer(error_stream, error_state, error_stream_error).
     
     :- type io_read_buffer ==
                 read_buffer(io.binary_input_stream, io.state, io.error).
     
     :- inst uniq_read_buffer == ground.   % XXX Should be unique.
     :- mode read_buffer_di == in(uniq_read_buffer).
     :- mode read_buffer_ui == in(uniq_read_buffer).
     :- mode read_buffer_uo == out(uniq_read_buffer).
     
         % new(NumBytes, Stream, State) creates a buffer which will read from
         % the stream specified by Stream and State in chunks of NumBytes bytes.
         % `NumBytes' must at least the size of a Mercury int, given by
         % int.bits_per_int.  If it is less, the size of an int will be used
         % instead.
         %
     :- func new(num_bytes, Stream, State) = read_buffer(Stream, State, Error)
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode new(in, in, di) = read_buffer_uo is det.
     
         % new(BitIndex, StartIndex, NumBits)
         % Create a buffer which reads bits from a bitmap, not from a stream.
         %
     :- func new_bitmap_reader(bitmap, bit_index, num_bits) = read_buffer.
     :- mode new_bitmap_reader(in, in, in) = read_buffer_uo is det.
     
     :- func new_bitmap_reader(bitmap) = read_buffer.
     :- mode new_bitmap_reader(in) = read_buffer_uo is det.
     
         % How many bits to be read does the buffer contain.
         %
     :- func num_buffered_bits(read_buffer(_, _, _)) = num_bits.
     :- mode num_buffered_bits(read_buffer_ui) = out is det.
     
         % How many bits need to be read to get to the next byte boundary.
         %
     :- func num_bits_to_byte_boundary(read_buffer(_, _, _)) = num_bits.
     :- mode num_bits_to_byte_boundary(read_buffer_ui) = out is det.
     
         % Find out whether there are bits left in the stream or an error
         % has been found.
         %
     :- pred buffer_status(stream.result(Error),
         read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode buffer_status(out, read_buffer_di, read_buffer_uo) is det.
     
         % Read a bit from the buffer.
         %
         % This implements the get/4 method of class stream.reader.
         %
     :- pred get_bit(stream.result(bool, Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bit(out, read_buffer_di, read_buffer_uo) is det.
     
         % get_bits(Index, NumBits, !Word, NumBitsRead, Result, !Buffer).
         %
         % Read NumBits bits from the buffer into a word starting at Index,
         % where the highest order bit is bit zero.
         % 0 =< NumBits =< int.bits_per_int.
         %
         % This implements the bulk_get/9 method of stream.bulk_reader.
         %
         % To read into the lower order bits of the word, use
         % `get_bits(bits_per_int - NumBits, NumBits, ...)'.
         %
     :- pred get_bits(bit_index, num_bits, word, word, num_bits,
         stream.res(Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bits(in, in, di, uo, out, out,
         read_buffer_di, read_buffer_uo) is det.
     
         % get_bitmap(!Bitmap, NumBitsRead, Result, !Buffer)
         %
         % Fill a bitmap from the buffered stream, returning the number
         % of bits read.
         %
         % Note that this is much more efficient if the initial position in
         % the buffer is at a byte boundary (for example after a call to
         % skip_padding_to_byte).
         %
     :- pred get_bitmap(bitmap, bitmap, num_bits,
         stream.res(Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bitmap(bitmap_di, bitmap_uo, out, out,
         read_buffer_di, read_buffer_uo) is det.
     
         % get_bitmap(Index, NumBits, !Bitmap, NumBitsRead, Result, !Buffer)
         %
         % Note that this is much more efficient if both Index and the initial
         % position in the buffer are both at a byte boundary (for example after
         % a call to skip_padding_to_byte).
         %
         % This implements the bulk_get method of stream.bulk_reader.
         %
     :- pred get_bitmap(bit_index, num_bits, bitmap, bitmap, num_bits,
         stream.res(Error), read_buffer(Stream, State, Error),
         read_buffer(Stream, State, Error))
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode get_bitmap(in, in, bitmap_di, bitmap_uo, out, out,
         read_buffer_di, read_buffer_uo) is det.
     
         % finalize(Buffer, Stream, State, BufferBM,
         %   IndexInBufferBM, NumBitsInBufferBM)
         %
         % Returns the stream, state and the unread buffered bits.
         %
     :- pred finalize(read_buffer(Stream, State, Error), Stream, State,
         bitmap, bit_index, num_bits)
         <= stream.bulk_reader(Stream, byte_index, bitmap, State, Error).
     :- mode finalize(read_buffer_di, out, uo, bitmap_uo, out, out) is det.
     
     %--------------------------------------------------%