[m-rev.] for review: add conversion functions from bytes to 32-bit integers

Julien Fischer jfischer at opturion.com
Fri Nov 3 22:44:37 AEDT 2017


I have committed this one -- I will deal with any review comments
separately.

Julien.

On Wed, 1 Nov 2017, Julien Fischer wrote:

>
> For review by anyone.
>
> --------------------
>
> Add conversion functions from bytes (uint8s) to 32-bit integers.
>
> library/int32.m:
> library/uint32.m:
>      As above.
>
> tests/hard_coded/Mmakefile:
> tests/hard_coded/int32_from_bytes.{m,exp}:
> tests/hard_coded/uint32_from_bytes.{m,exp}:
>      Test the new functions.
>
> Julien.
>
> diff --git a/library/int32.m b/library/int32.m
> index 28c10d1..4513b3f 100644
> --- a/library/int32.m
> +++ b/library/int32.m
> @@ -37,6 +37,20 @@
>
> :- func to_int(int32) = int.
>
> +    % from_bytes_le(Byte0, Byte1, Byte2, Byte3) = I32:
> +    % I32 is the int32 whose bytes are given in little-endian order by the
> +    % arguments from left-to-right (i.e. Byte0 is the least significant byte
> +    % and Byte3 is the most significant byte).
> +    %
> +:- func from_bytes_le(uint8, uint8, uint8, uint8) = int32.
> +
> +    % from_bytes_be(Byte0, Byte1, Byte2, Byte3) = U32:
> +    % I32 is the int32 whose bytes are given in big-endian order by the
> +    % arguments in left-to-right order (i.e. Byte0 is the most significant
> +    % byte and Byte3 is the least significant byte).
> +    %
> +:- func from_bytes_be(uint8, uint8, uint8, uint8) = int32.
> +
>  %---------------------------------------------------------------------------%
>
>     % Less than.
> @@ -342,6 +356,51 @@ to_int(_) = _ :-
>
> %---------------------------------------------------------------------------%
>
> +:- pragma foreign_proc("C",
> +    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (I32::out),
> +    [will_not_call_mercury, promise_pure, thread_safe, 
> will_not_modify_trail],
> +"
> +    unsigned char *int32_bytes = (unsigned char *) &I32;
> +#if defined(MR_BIG_ENDIAN)
> +    int32_bytes[0] = Byte3;
> +    int32_bytes[1] = Byte2;
> +    int32_bytes[2] = Byte1;
> +    int32_bytes[3] = Byte2;
> +#else
> +    int32_bytes[0] = Byte0;
> +    int32_bytes[1] = Byte1;
> +    int32_bytes[2] = Byte2;
> +    int32_bytes[3] = Byte3;
> +#endif
> +").
> +
> +:- pragma foreign_proc("Java",
> +    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (I32::out),
> +    [will_not_call_mercury, promise_pure, thread_safe],
> +"
> +    I32 = (Byte3 & 0xff) << 24 |
> +          (Byte2 & 0xff) << 16 |
> +          (Byte1 & 0xff) << 8  |
> +          (Byte0 & 0xff);
> +").
> +
> +:- pragma foreign_proc("C#",
> +    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (I32::out),
> +    [will_not_call_mercury, promise_pure, thread_safe],
> +"
> +    I32 = (Byte3 << 24 | Byte2 << 16 | Byte1 << 8 | Byte0);
> +").
> +
> +from_bytes_le(_, _, _, _) = _ :-
> +    sorry($module, "int32.from_bytes_le/4 NYI for Erlang").
> +
> +%---------------------------------------------------------------------------%
> +
> +from_bytes_be(Byte3, Byte2, Byte1, Byte0) =
> +    from_bytes_le(Byte0, Byte1, Byte2, Byte3).
> +
> +%---------------------------------------------------------------------------%
> +
>  X div Y = Div :-
>      Trunc = X // Y,
>      ( if
> diff --git a/library/uint32.m b/library/uint32.m
> index 6254a30..80fbefa 100644
> --- a/library/uint32.m
> +++ b/library/uint32.m
> @@ -35,6 +35,20 @@
>
> :- func cast_to_int(uint32) = int.
>
> +    % from_bytes_le(Byte0, Byte1, Byte2, Byte3) = U32:
> +    % U32 is the uint32 whose bytes are given in little-endian order by the
> +    % arguments from left-to-right (i.e. Byte0 is the least significant byte
> +    % and Byte3 is the most significant byte).
> +    %
> +:- func from_bytes_le(uint8, uint8, uint8, uint8) = uint32.
> +
> +    % from_bytes_be(Byte0, Byte1, Byte2, Byte3) = U32:
> +    % U32 is the uint32 whose bytes are given in big-endian order by the
> +    % arguments in left-to-right order (i.e. Byte0 is the most significant
> +    % byte and Byte3 is the least significant byte).
> +    %
> +:- func from_bytes_be(uint8, uint8, uint8, uint8) = uint32.
> +
>  %---------------------------------------------------------------------------%
>
>     % Less than.
> @@ -328,6 +342,51 @@ cast_to_int(_) = _ :-
>
> %---------------------------------------------------------------------------%
>
> +:- pragma foreign_proc("C",
> +    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (U32::out),
> +    [will_not_call_mercury, promise_pure, thread_safe, 
> will_not_modify_trail],
> +"
> +    unsigned char *uint32_bytes = (unsigned char *) &U32;
> +#if defined(MR_BIG_ENDIAN)
> +    uint32_bytes[0] = Byte3;
> +    uint32_bytes[1] = Byte2;
> +    uint32_bytes[2] = Byte1;
> +    uint32_bytes[3] = Byte2;
> +#else
> +    uint32_bytes[0] = Byte0;
> +    uint32_bytes[1] = Byte1;
> +    uint32_bytes[2] = Byte2;
> +    uint32_bytes[3] = Byte3;
> +#endif
> +").
> +
> +:- pragma foreign_proc("Java",
> +    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (U32::out),
> +    [will_not_call_mercury, promise_pure, thread_safe],
> +"
> +    U32 = (Byte3 & 0xff) << 24 |
> +          (Byte2 & 0xff) << 16 |
> +          (Byte1 & 0xff) << 8  |
> +          (Byte0 & 0xff);
> +").
> +
> +:- pragma foreign_proc("C#",
> +    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in) = (U32::out),
> +    [will_not_call_mercury, promise_pure, thread_safe],
> +"
> +    U32 = (uint) (Byte3 << 24 | Byte2 << 16 | Byte1 << 8 | Byte0);
> +").
> +
> +from_bytes_le(_, _, _, _) = _ :-
> +    sorry($module, "uint32.from_bytes_le/4 NYI for Erlang").
> +
> +%---------------------------------------------------------------------------%
> +
> +from_bytes_be(Byte3, Byte2, Byte1, Byte0) =
> +    from_bytes_le(Byte0, Byte1, Byte2, Byte3).
> +
> +%---------------------------------------------------------------------------%
> +
>  X div Y = X // Y.
>
> :- pragma inline('//'/2).
> diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
> index 15dadc6..4bdef3a 100644
> --- a/tests/hard_coded/Mmakefile
> +++ b/tests/hard_coded/Mmakefile
> @@ -174,6 +174,7 @@ ORDINARY_PROGS =	\
> 	 int_fold_up_down \
> 	 int_range_ops \
> 	 int16_from_bytes \
> +	int32_from_bytes \
> 	 integer_int16_conv \
> 	 integer_int32_conv \
> 	 integer_int8_conv \
> @@ -375,8 +376,9 @@ ORDINARY_PROGS =	\
> 	 type_to_term \
> 	 type_to_term_bug \
> 	 uc_export_enum \
> -	uint16_switch_test \
> 	 uint16_from_bytes \
> +	uint16_switch_test \
> +	uint32_from_bytes \
> 	 uint32_switch_test \
> 	 uint8_switch_test \
> 	 uint_switch_test \
> diff --git a/tests/hard_coded/int32_from_bytes.exp 
> b/tests/hard_coded/int32_from_bytes.exp
> index e69de29..54fd865 100644
> --- a/tests/hard_coded/int32_from_bytes.exp
> +++ b/tests/hard_coded/int32_from_bytes.exp
> @@ -0,0 +1,8 @@
> +-16777216i32
> +16711680i32
> +65280i32
> +255i32
> +255i32
> +65280i32
> +16711680i32
> +-16777216i32
> diff --git a/tests/hard_coded/int32_from_bytes.m 
> b/tests/hard_coded/int32_from_bytes.m
> index e69de29..a09c700 100644
> --- a/tests/hard_coded/int32_from_bytes.m
> +++ b/tests/hard_coded/int32_from_bytes.m
> @@ -0,0 +1,29 @@
> +:- module int32_from_bytes.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +:- implementation.
> +
> +:- import_module int32.
> +
> +main(!IO) :-
> +     Test1 = int32.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0xffu8),
> +     io.write_line(Test1, !IO),
> +     Test2 = int32.from_bytes_le(0x00u8, 0x00u8, 0xffu8, 0x00u8),
> +     io.write_line(Test2, !IO),
> +     Test3 = int32.from_bytes_le(0x00u8, 0xffu8, 0x00u8, 0x00u8),
> +     io.write_line(Test3, !IO),
> +     Test4 = int32.from_bytes_le(0xffu8, 0x00u8, 0x00u8, 0x00u8),
> +     io.write_line(Test4, !IO),
> +
> +     Test5 = int32.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0xffu8),
> +     io.write_line(Test5, !IO),
> +     Test6 = int32.from_bytes_be(0x00u8, 0x00u8, 0xffu8, 0x00u8),
> +     io.write_line(Test6, !IO),
> +     Test7 = int32.from_bytes_be(0x00u8, 0xffu8, 0x00u8, 0x00u8),
> +     io.write_line(Test7, !IO),
> +     Test8 = int32.from_bytes_be(0xffu8, 0x00u8, 0x00u8, 0x00u8),
> +     io.write_line(Test8, !IO).
> diff --git a/tests/hard_coded/uint32_from_bytes.exp 
> b/tests/hard_coded/uint32_from_bytes.exp
> index e69de29..f3ac7ea 100644
> --- a/tests/hard_coded/uint32_from_bytes.exp
> +++ b/tests/hard_coded/uint32_from_bytes.exp
> @@ -0,0 +1,8 @@
> +4278190080u32
> +16711680u32
> +65280u32
> +255u32
> +255u32
> +65280u32
> +16711680u32
> +4278190080u32
> diff --git a/tests/hard_coded/uint32_from_bytes.m 
> b/tests/hard_coded/uint32_from_bytes.m
> index e69de29..ca2fd4a 100644
> --- a/tests/hard_coded/uint32_from_bytes.m
> +++ b/tests/hard_coded/uint32_from_bytes.m
> @@ -0,0 +1,29 @@
> +:- module uint32_from_bytes.
> +:- interface.
> +
> +:- import_module io.
> +
> +:- pred main(io::di, io::uo) is det.
> +
> +:- implementation.
> +
> +:- import_module uint32.
> +
> +main(!IO) :-
> +     Test1 = uint32.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0xffu8),
> +     io.write_line(Test1, !IO),
> +     Test2 = uint32.from_bytes_le(0x00u8, 0x00u8, 0xffu8, 0x00u8),
> +     io.write_line(Test2, !IO),
> +     Test3 = uint32.from_bytes_le(0x00u8, 0xffu8, 0x00u8, 0x00u8),
> +     io.write_line(Test3, !IO),
> +     Test4 = uint32.from_bytes_le(0xffu8, 0x00u8, 0x00u8, 0x00u8),
> +     io.write_line(Test4, !IO),
> +
> +     Test5 = uint32.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0xffu8),
> +     io.write_line(Test5, !IO),
> +     Test6 = uint32.from_bytes_be(0x00u8, 0x00u8, 0xffu8, 0x00u8),
> +     io.write_line(Test6, !IO),
> +     Test7 = uint32.from_bytes_be(0x00u8, 0xffu8, 0x00u8, 0x00u8),
> +     io.write_line(Test7, !IO),
> +     Test8 = uint32.from_bytes_be(0xffu8, 0x00u8, 0x00u8, 0x00u8),
> +     io.write_line(Test8, !IO).
>


More information about the reviews mailing list