commit d6c950e614241eee903f3ce11afefe2fb59f5756
parent 870ad48578316a57310023a2a6cb160f71b2bf0d
Author: Andri Yngvason <andri@yngvason.is>
Date: Thu, 11 Feb 2021 21:31:48 +0000
strconv: utos: implement base 2, 8 and 16
Diffstat:
M | strconv/utos.ha | | | 54 | +++++++++++++++++++++++++++++++++++++++++++++++++----- |
1 file changed, 49 insertions(+), 5 deletions(-)
diff --git a/strconv/utos.ha b/strconv/utos.ha
@@ -1,11 +1,18 @@
use bytes;
use types;
-// Converts a u64 to a string, in base 10. The return value is statically
+// Converts a u64 to a string, in the given base. The return value is statically
// allocated and will be overwritten on subsequent calls; see [strings::dup] to
-// duplicate the result.
-export fn u64tos(u: u64) const str = {
+// duplicate the result. Valid bases are 2, 8, 10 and 16.
+export fn u64tosb(u: u64, base: uint) const str = {
static assert(types::U64_MAX == 18446744073709551615);
+ assert(base == 2 || base == 8 || base == 10 || base == 16);
+
+ static const lut: [_]rune = [
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ ];
+
static let buf: [21]u8 = [0...]; // 20 digits plus NUL
buf = [0...];
@@ -16,9 +23,9 @@ export fn u64tos(u: u64) const str = {
};
for (u > 0u64) {
- s.data[s.length] = '0': u32: u8 + (u % 10): u8;
+ s.data[s.length] = lut[(u % base: u64)]: u32: u8;
s.length += 1;
- u /= 10;
+ u /= base;
};
bytes::reverse(s.data[..s.length]);
@@ -26,6 +33,36 @@ export fn u64tos(u: u64) const str = {
return *(&s: *str);
};
+// Converts a u32 to a string, in the given base. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result. Valid bases are 2, 8, 10 and 16.
+export fn u32tosb(u: u32, base: uint) const str = u64tosb(u: u32, base);
+
+// Converts a u16 to a string, in the given base. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result. Valid bases are 2, 8, 10 and 16.
+export fn u16tosb(u: u16, base: uint) const str = u64tosb(u: u16, base);
+
+// Converts a u8 to a string, in the given base. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result. Valid bases are 2, 8, 10 and 16.
+export fn u8tosb(u: u8, base: uint) const str = u64tosb(u: u8, base);
+
+// Converts a uint to a string, in the given base. The return value is
+// statically allocated and will be overwritten on subsequent calls; see
+// [strings::dup] to duplicate the result. Valid bases are 2, 8, 10 and 16.
+export fn utosb(u: uint, base: uint) const str = u64tosb(u: uint, base);
+
+// Converts a size to a string, in the given base. The return value is
+// statically allocated and will be overwritten on subsequent calls; see
+// [strings::dup] to duplicate the result. Valid bases are 2, 8, 10 and 16.
+export fn ztosb(u: uint, base: uint) const str = u64tosb(u: uint, base);
+
+// Converts a u64 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result.
+export fn u64tos(u: u64) const str = u64tosb(u, 10u);
+
// Converts a u8 to a string, in base 10. The return value is statically
// allocated and will be overwritten on subsequent calls; see [strings::dup] to
// duplicate the result.
@@ -56,6 +93,13 @@ export fn ztos(z: size) const str = u64tos(z: u64);
// duplicate the result.
export fn uptrtos(uptr: uintptr) const str = u64tos(uptr: u64);
+@test fn utosb() void = {
+ assert("11010" == u64tosb(0b11010, 2));
+ assert("1234567" == u64tosb(0o1234567, 8));
+ assert("123456789" == u64tosb(123456789, 10));
+ assert("123456789ABCDEF" == u64tosb(0x123456789ABCDEF, 16));
+};
+
@test fn utos() void = {
const samples: [_]u64 = [
1234,