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-2019, 2022, 2024 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. %--------------------------------------------------% % None of these instances work because of limitations in the type and % RTTI systems. %
Next: bit_buffer.write, Previous: bit_buffer, Up: Top [Contents]