Files
mercury/library/bit_buffer.m
Zoltan Somogyi a19bcaaed5 Updates to programming style in the library.
library/bt_array.m:
    Reorder the arguments of the resize and shrink predicates
    to make them easier to use with state variables.

tests/general/array_test.m:
    Update the test calls to these two predicates.

library/version_array2d.m:
    Rewrite part of this module using a programming style that includes
    variable names that are longer than one character :-(. In the absence
    of comprehensive, or even basic, test cases, leave the rest using
    the old style.

    Add a non-field-syntax lookup operation.

    Mark the site of a probable bug.

library/version_bitmap.m:
    Add non-field-syntax versions of the get_bit and set_bit operations.

NEWS.md:
    Announce the reordering and the new predicates above.

library/getopt.m:
library/getopt_io.m:
    Apply to getopt_io.m an update that was previously applied to getopt.m,
    even though getopt.m is now computed from getopt_io.m.

library/array2d.m:
library/bit_buffer.m:
library/bit_buffer.read.m:
library/bit_buffer.write.m:
library/bitmap.m:
library/cord.m:
library/edit_distance.m:
library/edit_seq.m:
library/fat_sparse_bitset.m:
library/fatter_sparse_bitset.m:
library/list.m:
library/one_or_more.m:
library/pair.m:
library/ra_list.m:
library/rbtree.m:
library/set_bbbtree.m:
library/set_ctree234.m:
library/set_ordlist.m:
library/set_tree234.m:
library/set_unordlist.m:
library/solutions.m:
library/sparse_bitset.m:
library/test_bitset.m:
library/thread.barrier.m:
library/thread.m:
library/thread.semaphore.m:
library/time.m:
library/tree_bitset.m:
library/version_array.m:
library/version_hash_table.m:
library/version_store.m:
    General updates to style, the main ones being the following.

    Using standard names for type variables:

    - K and V for key and value types in map-like structures
    - A to F for types of accumulators
    - T for most everything else, possibly with a numeric suffix
      to distinguish two separate types that nevertheless play
      similar roles.

    (I left descriptive type var names such as Stream and Store unchanged.)

    Adding or expanding descriptions of exported predicates and functions.

    Declaring and defining field syntax getters and setters without using ^,
    while keeping the use of field syntax, including ^, in the operations'
    descriptions.

    Defining field syntax operations operations in terms of the
    non-field-syntax versions, not vice versa.

    Defining function versions of operations in terms of the predicate
    versions, not vice versa.
2024-12-29 20:09:09 +11:00

357 lines
12 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
% Copyright (C) 2007, 2009 The University of Melbourne
% Copyright (C) 2014, 2018, 2024 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%---------------------------------------------------------------------------%
% File: bit_buffer.m.
% Main author: stayl.
% Stability: low.
%
% A bit buffer provides an interface between bit-oriented I/O requests
% and byte-oriented streams. The useful part of the interface is defined
% in bit_buffer.read and bit_buffer.write.
%
% 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.
:- interface.
:- import_module bitmap.
:- import_module stream.
:- include_module bit_buffer.read.
:- include_module bit_buffer.write.
% An error_stream throws an `error_stream_error' exception if any of
% its output methods are called, or returns an `error_stream_error'
% if any of its input methods are called.
%
:- type error_stream ---> error_stream.
:- type error_state ---> error_state.
:- type error_stream_error ---> error_stream_error.
:- instance stream.error(error_stream_error).
:- instance stream.stream(error_stream, error_state).
:- instance stream.input(error_stream, error_state).
:- instance stream.bulk_reader(error_stream, byte_index, bitmap,
error_state, error_stream_error).
:- instance stream.output(error_stream, error_state).
:- instance stream.writer(error_stream, bitmap.slice, error_state).
%---------------------------------------------------------------------------%
:- implementation.
:- import_module bool.
:- import_module exception.
:- import_module int.
:- import_module list.
:- import_module require.
:- instance stream.error(error_stream_error) where
[
error_message(_) = "method called for error_stream"
].
:- instance stream.stream(error_stream, error_state) where
[
name(_Stream, "error_stream", !State)
].
:- instance stream.input(error_stream, error_state) where
[].
:- instance stream.bulk_reader(error_stream, byte_index, bitmap,
error_state, error_stream_error) where
[
bulk_get(_, _, _, !BM, 0, error(error_stream_error), !State)
].
:- instance stream.output(error_stream, error_state) where
[
flush(_, !State) :- throw(error_stream_error)
].
:- instance stream.writer(error_stream, bitmap.slice, error_state)
where
[
put(_, _, _, _) :- throw(error_stream_error)
].
% The bitmap has room for the chunk size given as an argument
% to `new', plus a word.
%
% This means that a for a write buffer a word can always
% be written to the buffer, and the buffer will be flushed
% if the position is greater than the chunk size.
%
% For a read_buffer, bits will be read from the input stream
% and placed starting at bit number `bits_per_int'. When the
% buffer is nearly exhausted (less than a word left), the last
% word is copied to the start of the buffer and the buffer is
% refilled.
%
:- type bit_buffer(Stream, State, Error)
---> bit_buffer(
mer_bitmap :: bitmap,
mer_pos :: bit_index,
mer_size :: num_bits,
mer_use_stream :: bool,
mer_stream :: Stream,
mer_state :: State,
% For write buffers only.
% If we are not writing to a stream, keep a list of filled
% bitmaps in reverse order. These will be concatenated into
% a single bitmap by finalize_to_bitmap.
%
mer_filled_bitmaps :: list(bitmap),
% For read buffers only. The first error found when reading
% from a stream. Subsequent calls will return this error.
mer_read_status :: stream.res(Error)
).
:- type bit_buffer(Stream, State) == bit_buffer(Stream, State, {}).
% XXX These should be unique.
:- mode bit_buffer_ui == in.
:- mode bit_buffer_di == in.
:- mode bit_buffer_uo == out.
% Allocating memory for every read or write would be bad,
% so we manually perform destructive update in C.
%
:- pragma foreign_decl("C", "
typedef struct {
MR_BitmapPtr ML_bit_buffer_bitmap;
MR_Integer ML_bit_buffer_pos;
MR_Integer ML_bit_buffer_size;
MR_Word ML_bit_buffer_use_stream;
MR_Word ML_bit_buffer_stream;
MR_Word ML_bit_buffer_state;
MR_Word ML_bit_buffer_filled_bitmaps;
MR_Word ML_bit_buffer_read_status;
} ML_BitBuffer;
typedef ML_BitBuffer *ML_BitBufferPtr;
").
:- pragma foreign_type("C", bit_buffer(Stream, State, Error),
"ML_BitBufferPtr", [can_pass_as_mercury_type]).
:- func new_buffer(bitmap, bit_index, num_bits, bool, Stream, State) =
bit_buffer(Stream, State, Error).
new_buffer(BM, Pos, Size, UseStream, Stream, State) =
( if Size =< 0 then
func_error($pred, "invalid buffer size")
else
new_buffer_2(BM, Pos, Size, UseStream, Stream, State, ok)
).
:- func new_buffer_2(bitmap, num_bits, bit_index, bool,
Stream, State, stream.res(Error)) = bit_buffer(Stream, State, Error).
new_buffer_2(BM, Pos, Size, UseStream, Stream, State, ReadStatus) =
bit_buffer(BM, Pos, Size, UseStream, Stream, State, [], ReadStatus).
:- pragma foreign_proc("C",
new_buffer_2(BM::in, Pos::in, Size::in, UseStream::in,
Stream::in, State::in, ReadStatus::in) = (Buffer::out),
[will_not_call_mercury, promise_pure, thread_safe],
"{
MR_incr_hp_type_msg(Buffer, ML_BitBuffer, MR_ALLOC_ID,
""bit_buffer.bit_buffer/3"");
Buffer->ML_bit_buffer_bitmap = BM;
Buffer->ML_bit_buffer_pos = Pos;
Buffer->ML_bit_buffer_size = Size;
Buffer->ML_bit_buffer_use_stream = UseStream;
Buffer->ML_bit_buffer_stream = Stream;
Buffer->ML_bit_buffer_state = State;
Buffer->ML_bit_buffer_filled_bitmaps = MR_list_empty_msg(MR_ALLOC_ID);
Buffer->ML_bit_buffer_read_status = ReadStatus;
}").
:- func (bit_buffer(_, _, _)::bit_buffer_ui) ^ bitmap =
(bitmap::bitmap_uo) is det.
:- func (bit_buffer(_, _, _)::bit_buffer_ui) ^ pos = (int::out) is det.
:- func (bit_buffer(_, _, _)::bit_buffer_ui) ^ size = (int::out) is det.
:- func (bit_buffer(_, _, _)::bit_buffer_ui) ^ use_stream = (bool::out) is det.
:- func (bit_buffer(Stream, _, _)::bit_buffer_ui) ^ stream =
(Stream::out) is det.
:- func (bit_buffer(_, State, _)::bit_buffer_ui) ^ state = (State::uo) is det.
:- func (bit_buffer(_, _, _)::bit_buffer_ui) ^ filled_bitmaps =
(list(bitmap)::out) is det.
:- func (bit_buffer(_, _, Error)::bit_buffer_ui) ^ read_status =
(stream.res(Error)::out) is det.
:- pragma foreign_proc("C",
bitmap(Buffer::bit_buffer_ui) = (BM::bitmap_uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
BM = Buffer->ML_bit_buffer_bitmap;
").
Buffer ^ bitmap = Buffer ^ mer_bitmap.
:- pragma foreign_proc("C",
pos(Buffer::bit_buffer_ui) = (Pos::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Pos = Buffer->ML_bit_buffer_pos;
").
Buffer ^ pos = Buffer ^ mer_pos.
:- pragma foreign_proc("C",
size(Buffer::bit_buffer_ui) = (Size::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Size = Buffer->ML_bit_buffer_size;
").
Buffer ^ size = Buffer ^ mer_size.
:- pragma foreign_proc("C",
use_stream(Buffer::bit_buffer_ui) = (UseStream::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
UseStream = Buffer->ML_bit_buffer_use_stream;
").
Buffer ^ use_stream = Buffer ^ mer_use_stream.
:- pragma foreign_proc("C",
stream(Buffer::bit_buffer_ui) = (Stream::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Stream = Buffer->ML_bit_buffer_stream;
").
Buffer ^ stream = Buffer ^ mer_stream.
:- pragma foreign_proc("C",
state(Buffer::bit_buffer_ui) = (State::uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
State = Buffer->ML_bit_buffer_state;
").
Buffer ^ state = unsafe_promise_unique(Buffer ^ mer_state).
:- pragma foreign_proc("C",
filled_bitmaps(Buffer::bit_buffer_ui) = (FilledBMs::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
FilledBMs = Buffer->ML_bit_buffer_filled_bitmaps;
").
Buffer ^ filled_bitmaps = Buffer ^ mer_filled_bitmaps.
:- pragma foreign_proc("C",
read_status(Buffer::bit_buffer_ui) = (ReadStatus::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ReadStatus = Buffer->ML_bit_buffer_read_status;
").
Buffer ^ read_status = Buffer ^ mer_read_status.
:- pred set_all(bitmap::bitmap_di, bit_index::in, num_bits::in, State::di,
list(bitmap)::in, bit_buffer(Stream, State, Error)::bit_buffer_di,
bit_buffer(Stream, State, Error)::bit_buffer_uo) is det.
set_all(BM, Pos, Size, State, FilledBMs, !Buffer) :-
!Buffer ^ mer_bitmap := BM,
!Buffer ^ mer_pos := Pos,
!Buffer ^ mer_state := State,
!Buffer ^ mer_filled_bitmaps := FilledBMs,
!Buffer ^ mer_size := Size.
:- pragma foreign_proc("C",
set_all(BM::bitmap_di, Pos::in, Size::in, State::di, FilledBMs::in,
Buffer0::bit_buffer_di, Buffer::bit_buffer_uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
Buffer = Buffer0;
Buffer->ML_bit_buffer_bitmap = BM;
Buffer->ML_bit_buffer_pos = Pos;
Buffer->ML_bit_buffer_size = Size;
Buffer->ML_bit_buffer_state = State;
Buffer->ML_bit_buffer_filled_bitmaps = FilledBMs;
").
:- pred set_bitmap(bitmap::bitmap_di, bit_index::in,
bit_buffer(Stream, State, Error)::bit_buffer_di,
bit_buffer(Stream, State, Error)::bit_buffer_uo) is det.
set_bitmap(BM, Pos, !Buffer) :-
!Buffer ^ mer_bitmap := BM,
!Buffer ^ mer_pos := Pos.
:- pragma foreign_proc("C",
set_bitmap(BM::bitmap_di, Pos::in,
Buffer0::bit_buffer_di, Buffer::bit_buffer_uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
Buffer = Buffer0;
Buffer->ML_bit_buffer_bitmap = BM;
Buffer->ML_bit_buffer_pos = Pos;
").
:- pred set_state(State::di,
bit_buffer(Stream, State, Error)::bit_buffer_di,
bit_buffer(Stream, State, Error)::bit_buffer_uo) is det.
set_state(State, !Buffer) :-
!:Buffer = !.Buffer ^ mer_state := State.
:- pragma foreign_proc("C",
set_state(State::di, Buffer0::bit_buffer_di, Buffer::bit_buffer_uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
Buffer = Buffer0;
Buffer->ML_bit_buffer_state = State;
").
:- pred set_use_stream(bool::in,
bit_buffer(Stream, State, Error)::bit_buffer_di,
bit_buffer(Stream, State, Error)::bit_buffer_uo) is det.
set_use_stream(UseStream, !Buffer) :-
!:Buffer = !.Buffer ^ mer_use_stream := UseStream.
:- pragma foreign_proc("C",
set_use_stream(UseStream::in,
Buffer0::bit_buffer_di, Buffer::bit_buffer_uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
Buffer = Buffer0;
Buffer->ML_bit_buffer_use_stream = UseStream;
").
:- pred set_read_status(stream.res(Error)::in,
bit_buffer(Stream, State, Error)::bit_buffer_di,
bit_buffer(Stream, State, Error)::bit_buffer_uo) is det.
set_read_status(ReadStatus, !Buffer) :-
!:Buffer = !.Buffer ^ mer_read_status := ReadStatus.
:- pragma foreign_proc("C",
set_read_status(ReadStatus::in,
Buffer0::bit_buffer_di, Buffer::bit_buffer_uo),
[will_not_call_mercury, promise_pure, thread_safe],
"
Buffer = Buffer0;
Buffer->ML_bit_buffer_read_status = ReadStatus;
").
%---------------------------------------------------------------------------%
:- end_module bit_buffer.
%---------------------------------------------------------------------------%