Next: bit_buffer.write, Previous: bit_buffer, Up: Top [Contents]
%--------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%--------------------------------------------------%
% Copyright (C) 2007, 2010-2011 The University of Melbourne
% Copyright (C) 2014-2015, 2018 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%--------------------------------------------------%
% 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.
%--------------------------------------------------%
Next: bit_buffer.write, Previous: bit_buffer, Up: Top [Contents]