[m-rev.] for review: reading multibyte integers from binary file streams

Julien Fischer jfischer at opturion.com
Sun Jan 27 12:48:05 AEDT 2019


Hi Zoltan,

On Sun, 27 Jan 2019, Zoltan Somogyi wrote:

> On Sun, 20 Jan 2019 04:36:28 +0000 (UTC), Julien Fischer <jfischer at opturion.com> wrote:
>> I'm going to go ahead and commit this one now; I'll deal with any further
>> review comments separately.
>
> Sorry for the late review. I am concerned that your code may try to
> reverse the bytes even inside uint8s, which would fail because there is
> no function to perform that noop. Can you have a look at *my* review,
> which takes the form of the attached diff?

> diff --git a/library/io.m b/library/io.m
> index 098f694..96b84d1 100644
> --- a/library/io.m
> +++ b/library/io.m
> @@ -885,21 +885,22 @@
>  :- pred read_binary_uint8(io.binary_input_stream::in, io.result(uint8)::out,
>      io::di, io::uo) is det.
> 
> -    % The following predicates read multibyte integer values from the current
> -    % binary input stream or from the specified binary input stream.
> +    % The following predicates read multibyte integer values, either
> +    % from the current binary input stream, or from the specified
> +    % binary input stream.
>      %
>      % The names of these predicates have the form:
>      %
>      %    read_binary_<TYPE><SUFFIX>
>      %
>      % where <TYPE> is the name of one of the Mercury multibyte fixed size
> -    % integer types. <SUFFIX> is optional and specifies what order the
> -    % bytes in input stream that make up the multibyte integer occur
> -    % in. It may be one of:
> +    % integer types. The optional <SUFFIX> specifies the order in which
> +    % the bytes that make up the multibyte integer occur in input stream.
> +    % The suffix may be one of:
>      %
> -    %     no suffix - native byte order of the underlying platform.
> -    %     "_le"     - little endian byte order.
> -    %     "_be"     - big endian byte order.
> +    % "_le":    the bytes are in little endian byte order.
> +    % "_be":    the bytes are in big endian byte order.
> +    % none:     the bytes are in the byte order of the underlying platform.

I have no objection to your change of formatting here, except that it is
no longer consistent with that of the documentation of the
write_binary_<TYPE>_SUFFIX> predicates.  If this changes, then so should
that.

...

>  // Build an n-bit unsigned integer using the bytes stored in the array
> -// 'buffer'.  The order of the bytes in the buffer are given by 'byte_order'.
> +// 'buffer'. The order of the bytes in the buffer are given by 'byte_order'.
>  // The result is assigned to the lvalue 'value'
>  //
>  // We have two definitions of this macro, one for big-endian machines
> -// and one for little-endian machines.
> +// and one for little-endian machines. The special treatment of n == 8
> +// is due to the fact that the notion of ""reversing the bytes"" does not
> +// make sense for one byte integers.

While your change to handle N = 8 is harmless, it's also never going
to be used.  The result type used to handle uint8s is different.  I suggest
just documenting that MR_build_uintN is for use with N={16,32,64} directly
above the macro definition and leaving it at that.

>  //
>  #if defined(MR_BIG_ENDIAN)
>  #define ML_build_uintN(n, byte_order, buffer, value)                 \
>      do {                                                             \
> -        if (byte_order == ML_LITTLE_ENDIAN) {                        \
> +        if (((n) != 8) && ((byte_order) == ML_LITTLE_ENDIAN)) {      \
>              value = ML_REVERSE_BYTES_FUNC(n)(                        \
> -                *((ML_N_BIT_INT_T(n) *) buffer));                    \
> +                *((ML_N_BIT_UINT_T(n) *) buffer));                   \
>          } else {                                                     \
> -            value = *((ML_N_BIT_INT_T(n) *) buffer);                 \
> +            value = *((ML_N_BIT_UINT_T(n) *) buffer);                \
>          }                                                            \
>      } while (0)
>  #else
>  #define ML_build_uintN(n, byte_order, buffer, value)                 \
>      do {                                                             \
> -        if (byte_order == ML_LITTLE_ENDIAN) {                        \
> -            value = *((ML_N_BIT_INT_T(n) *) buffer);                 \
> +        if (((n) == 8) || ((byte_order) == ML_LITTLE_ENDIAN)) {      \
> +            value = *((ML_N_BIT_UINT_T(n) *) buffer);                \
>          } else {                                                     \
>              value = ML_REVERSE_BYTES_FUNC(n)(                        \
> -                *((ML_N_BIT_INT_T(n) *) buffer));                    \
> +                *((ML_N_BIT_UINT_T(n) *) buffer));                   \
>          }                                                            \
>      } while (0)
>  #endif

The rest looks fine.

Julien.


More information about the reviews mailing list