utos.ha (3369B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use bytes; 5 use types; 6 7 // Converts a u64 to a string. The return value is statically allocated and will 8 // be overwritten on subsequent calls; see [[strings::dup]] to duplicate the 9 // result. 10 export fn u64tos(u: u64, b: base = base::DEC) const str = { 11 static assert(types::U64_MAX == 18446744073709551615); 12 static let buf: [64]u8 = [0...]; // 64 binary digits 13 14 static const lut_upper = [ 15 '0', '1', '2', '3', '4', '5', '6', '7', 16 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 17 ], lut_lower = [ 18 '0', '1', '2', '3', '4', '5', '6', '7', 19 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 20 ]; 21 const lut = if (b != base::HEX_LOWER) &lut_upper else { 22 b = base::HEX_UPPER; 23 yield &lut_lower; 24 }; 25 26 const b: uint = if (b == base::DEFAULT) base::DEC else b; 27 28 let s = types::string { data = &buf, ... }; 29 if (u == 0) { 30 buf[s.length] = '0'; 31 s.length += 1z; 32 }; 33 34 for (u > 0u64) { 35 buf[s.length] = lut[u % b: u64]: u8; 36 s.length += 1; 37 u /= b; 38 }; 39 40 bytes::reverse(buf[..s.length]); 41 return *(&s: *str); 42 }; 43 44 // Converts a u32 to a string. The return value is statically allocated and will 45 // be overwritten on subsequent calls; see [[strings::dup]] to duplicate the 46 // result. 47 export fn u32tos(u: u32, b: base = base::DEC) const str = u64tos(u, b); 48 49 // Converts a u16 to a string. The return value is statically allocated and will 50 // be overwritten on subsequent calls; see [[strings::dup]] to duplicate the 51 // result. 52 export fn u16tos(u: u16, b: base = base::DEC) const str = u64tos(u, b); 53 54 // Converts a u8 to a string. The return value is statically allocated and will 55 // be overwritten on subsequent calls; see [[strings::dup]] to duplicate the 56 // result. 57 export fn u8tos(u: u8, b: base = base::DEC) const str = u64tos(u, b); 58 59 // Converts a uint to a string. The return value is statically allocated and 60 // will be overwritten on subsequent calls; see [[strings::dup]] to duplicate 61 // the result. 62 export fn utos(u: uint, b: base = base::DEC) const str = u64tos(u, b); 63 64 // Converts a size to a string. The return value is statically allocated and 65 // will be overwritten on subsequent calls; see [[strings::dup]] to duplicate 66 // the result. 67 export fn ztos(u: size, b: base = base::DEC) const str = u64tos(u, b); 68 69 // Converts a uintptr to a string. The return value is statically allocated and 70 // will be overwritten on subsequent calls; see [[strings::dup]] to duplicate 71 // the result. 72 export fn uptrtos(uptr: uintptr, b: base = base::DEC) const str = u64tos(uptr: u64, b); 73 74 @test fn utos_bases() void = { 75 assert("11010" == u64tos(0b11010, base::BIN)); 76 assert("1234567" == u64tos(0o1234567, base::OCT)); 77 assert("123456789" == u64tos(123456789, base::DEC)); 78 assert("123456789ABCDEF" == u64tos(0x123456789ABCDEF, base::HEX)); 79 assert("123456789ABCDEF" == u64tos(0x123456789ABCDEF, base::HEX_UPPER)); 80 assert("123456789abcdef" == u64tos(0x123456789ABCDEF, base::HEX_LOWER)); 81 assert("1111111111111111111111111111111111111111111111111111111111111111" 82 == u64tos(types::U64_MAX, base::BIN)); 83 }; 84 85 @test fn utos() void = { 86 const samples: [_]u64 = [ 87 1234, 88 4321, 89 types::U64_MIN, 90 types::U64_MAX, 91 ]; 92 const expected = [ 93 "1234", 94 "4321", 95 "0", 96 "18446744073709551615", 97 ]; 98 99 for (let i = 0z; i < len(samples); i += 1) { 100 const s = u64tos(samples[i]); 101 assert(s == expected[i]); 102 }; 103 };