[m-rev.] for review: add uint64 to string conversin for bases 8 and 16
Julien Fischer
jfischer at opturion.com
Sun Dec 13 19:37:01 AEDT 2020
For review by anyone.
--------------------
Add uint64 to string conversion for bases 8 and 16.
library/string.m:
Add functions for converting uint64s to strings of base 8 or base 16
digits. For most integer types we can cast to a uint and then use the
uint versions of these operations but for 64-bit types we cannot since
on some of our supported platforms uints are 32-bit.
NEWS:
Announce the additions.
tests/hard_coded/Mmakefile:
tests/hard_coded/uint64_string_conv.{m,exp}:
Add a test of the new functions.
diff --git a/NEWS b/NEWS
index c878099..9caa794 100644
--- a/NEWS
+++ b/NEWS
@@ -152,6 +152,9 @@ Changes to the Mercury standard library
- func `uint_to_hex_string/1`
- func `uint_to_uc_hex_string/1`
- func `uint_to_octal_string/1`
+ - func `uint64_to_hex_string/1`
+ - func `uint64_to_uc_hex_string/1`
+ - func `uint64_to_octal_string/1`
* The following function symbols have been added to the type `poly_type`:
diff --git a/library/string.m b/library/string.m
index 35519ea..c02beab 100644
--- a/library/string.m
+++ b/library/string.m
@@ -1498,6 +1498,20 @@
:- func int64_to_string(int64::in) = (string::uo) is det.
:- func uint64_to_string(uint64::in) = (string::uo) is det.
+ % Convert an unsigned 64-bit integer to a string in base 16.
+ % Alphabetic digits will be lowercase (e.g. a-f).
+ %
+:- func uint64_to_hex_string(uint64::in) = (string::uo) is det.
+
+ % Convert an unsigned 64-bit integer to a string in base 16.
+ % Alphabetic digits will be uppercase (e.g. A-F).
+ %
+:- func uint64_to_uc_hex_string(uint64::in) = (string::uo) is det.
+
+ % Convert an unsigned 64-bit integer to a string in base 8.
+ %
+:- func uint64_to_octal_string(uint64::in) = (string::uo) is det.
+
% Convert a float to a string.
% In the current implementation, the resulting float will be in the form
% that it was printed using the format string "%#.<prec>g".
@@ -5857,6 +5871,86 @@ int_to_base_string_group_2(NegN, Base, Curr, GroupLength, Sep, Str) :-
%---------------------%
+:- pragma foreign_proc("C",
+ uint64_to_hex_string(U64::in) = (S::uo),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+ char buffer[21]; // 20 for digits, 1 for nul.
+ sprintf(buffer, ""%"" PRIx64, U64);
+ MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+ strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+ uint64_to_hex_string(U64::in) = (S::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ S = U64.ToString(""x"");
+").
+
+:- pragma foreign_proc("Java",
+ uint64_to_hex_string(U64::in) = (S::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ S = java.lang.Long.toHexString(U64);
+").
+
+%---------------------%
+
+:- pragma foreign_proc("C",
+ uint64_to_uc_hex_string(U64::in) = (S::uo),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+ char buffer[21]; // 20 for digits, 1 for nul.
+ sprintf(buffer, ""%"" PRIX64, U64);
+ MR_allocate_aligned_string_msg(S, strlen(buffer), MR_ALLOC_ID);
+ strcpy(S, buffer);
+").
+
+:- pragma foreign_proc("C#",
+ uint64_to_uc_hex_string(U64::in) = (S::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ S = U64.ToString(""X"");
+").
+
+:- pragma foreign_proc("Java",
+ uint64_to_uc_hex_string(U64::in) = (S::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ S = java.lang.Long.toHexString(U64).toUpperCase();
+").
+
+:- pragma foreign_proc("C",
+ uint64_to_octal_string(U64::in) = (Str::uo),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+ does_not_affect_liveness, no_sharing],
+"
+ char buffer[23]; // 22 for digits, 1 for nul.
+ sprintf(buffer, ""%"" PRIo64, U64);
+ MR_allocate_aligned_string_msg(Str, strlen(buffer), MR_ALLOC_ID);
+ strcpy(Str, buffer);
+").
+
+:- pragma foreign_proc("C#",
+ uint64_to_octal_string(U64::in) = (Str::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ // We need to cast to a long here since C# does not provide an overloading
+ // of ToString() for ulongs. This works since ToString() will use the
+ // unsigned representation for non-decimal bases.
+ Str = System.Convert.ToString((long) U64, 8);
+").
+
+:- pragma foreign_proc("Java",
+ uint64_to_octal_string(U64::in) = (Str::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ Str = java.lang.Long.toOctalString(U64);
+").
+
+%---------------------%
+
float_to_string(Float) = S2 :-
float_to_string(Float, S2).
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 1ff7d49..2ba8735 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -444,6 +444,7 @@ ORDINARY_PROGS = \
uint32_to_uint64 \
uint64_from_bytes \
uint64_ground_term \
+ uint64_string_conv \
uint64_switch_test \
uint8_switch_test \
uint_switch_test \
diff --git a/tests/hard_coded/uint64_string_conv.exp b/tests/hard_coded/uint64_string_conv.exp
index e69de29..ffe9df3 100644
--- a/tests/hard_coded/uint64_string_conv.exp
+++ b/tests/hard_coded/uint64_string_conv.exp
@@ -0,0 +1,29 @@
+Decimal Octal Hex HEX
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+7 7 7 7
+8 10 8 8
+9 11 9 9
+10 12 a A
+11 13 b B
+12 14 c C
+13 15 d D
+14 16 e E
+15 17 f F
+16 20 10 10
+32 40 20 20
+64 100 40 40
+127 177 7f 7F
+128 200 80 80
+255 377 ff FF
+256 400 100 100
+32767 77777 7fff 7FFF
+65535 177777 ffff FFFF
+2147483647 17777777777 7fffffff 7FFFFFFF
+4294967295 37777777777 ffffffff FFFFFFFF
+9223372036854775807 777777777777777777777 7fffffffffffffff 7FFFFFFFFFFFFFFF
+18446744073709551615 1777777777777777777777 ffffffffffffffff FFFFFFFFFFFFFFFF
+
diff --git a/tests/hard_coded/uint64_string_conv.m b/tests/hard_coded/uint64_string_conv.m
index e69de29..5b3e909 100644
--- a/tests/hard_coded/uint64_string_conv.m
+++ b/tests/hard_coded/uint64_string_conv.m
@@ -0,0 +1,69 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+% Test conversion of uint64s to strings.
+%---------------------------------------------------------------------------%
+
+:- module uint64_string_conv.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module list.
+:- import_module string.
+:- import_module uint64.
+
+main(!IO) :-
+ io.format("%-22s %-24s %-22s%-22s\n", [s("Decimal"), s("Octal"), s("Hex"),
+ s("HEX")], !IO),
+ list.foldl(do_test, test_values, !IO),
+ io.nl(!IO).
+
+:- pred do_test(uint64::in, io::di, io::uo) is det.
+
+do_test(U, !IO) :-
+ Decimal = uint64_to_string(U),
+ Octal = uint64_to_octal_string(U),
+ Hex = uint64_to_hex_string(U),
+ HexUC = uint64_to_uc_hex_string(U),
+ io.format("%-22s %-24s %-22s%-22s\n",
+ [s(Decimal), s(Octal), s(Hex), s(HexUC)], !IO).
+
+:- func test_values = list(uint64).
+
+test_values = [
+ 0u64,
+ 1u64,
+ 2u64,
+ 3u64,
+ 4u64,
+ 7u64,
+ 8u64,
+ 9u64,
+ 10u64,
+ 11u64,
+ 12u64,
+ 13u64,
+ 14u64,
+ 15u64,
+ 16u64,
+ 32u64,
+ 64u64,
+ 127u64,
+ 128u64,
+ 255u64,
+ 256u64,
+ 32767u64,
+ 65535u64,
+ 2147483647u64,
+ 4294967295u64,
+ 9223372036854775807u64,
+ 18446744073709551615u64
+].
More information about the reviews
mailing list