diff --git a/libraries/libstratosphere/source/os/impl/os_utility.cpp b/libraries/libstratosphere/source/os/impl/os_utility.cpp index 3a0f709f9..0498b469e 100644 --- a/libraries/libstratosphere/source/os/impl/os_utility.cpp +++ b/libraries/libstratosphere/source/os/impl/os_utility.cpp @@ -18,25 +18,87 @@ namespace ams::os::impl { - void ExpandUnsignedValueToAscii(char *dst, u64 value) { - /* Determine size needed. */ - constexpr size_t SizeNeeded = (BITSIZEOF(value) / 4) * sizeof(char); + namespace { - /* Write null-terminator. */ - dst[SizeNeeded] = '\x00'; + constexpr void ExpandUnsignedValueToAsciiImpl(char *dst, u64 value) { + /* Determine size needed. */ + constexpr size_t SizeNeeded = (BITSIZEOF(value) / 4) * sizeof(char); - /* Write characters. */ - for (size_t i = 0; i < SizeNeeded; ++i) { - /* Determine current character. */ - const auto nybble = (value & 0xF); - const char cur_c = (nybble < 10) ? ('0' + nybble) : ('A' + nybble - 10); + /* Write null-terminator. */ + dst[SizeNeeded] = '\x00'; - /* Write current character. */ - dst[SizeNeeded - 1 - i] = cur_c; + /* Write characters. */ + for (size_t i = 0; i < SizeNeeded; ++i) { + /* Determine current character. */ + const auto nybble = (value & 0xF); + const char cur_c = (nybble < 10) ? ('0' + nybble) : ('A' + nybble - 10); - /* Shift to next nybble. */ - value >>= 4; + /* Write current character. */ + dst[SizeNeeded - 1 - i] = cur_c; + + /* Shift to next nybble. */ + value >>= 4; + } } + } + void ExpandUnsignedValueToAscii(char *dst, u64 value) { + return ExpandUnsignedValueToAsciiImpl(dst, value); + } + + /* Test correctness. */ + #if 0 + namespace { + + consteval bool TestExpandUnsignedValueToAsciiImpl(const char *expected, u64 value) { + /* Create buffer. */ + char buffer[17] = { + '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC', '\xCC' + }; + + /* Validate buffer is initially garbage. */ + for (size_t i = 0; i < util::size(buffer); ++i) { + if (buffer[i] != '\xCC') { + return false; + } + } + + /* Expand the value into the buffer. */ + ExpandUnsignedValueToAsciiImpl(buffer, value); + + /* Verify the result. */ + for (size_t i = 0; i < util::size(buffer); ++i) { + if (buffer[i] != expected[i]) { + return false; + } + } + + /* Verify null-termination. */ + if (buffer[util::size(buffer) - 1] != 0) { + return false; + } + + return true; + } + + #define DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(v) static_assert(TestExpandUnsignedValueToAsciiImpl( #v , UINT64_C(0x##v))) + + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(0000000000000000); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(FFFFFFFFFFFFFFFF); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(FFFFFFFF00000000); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(00000000FFFFFFFF); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(FFFF0000FFFF0000); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(0000FFFF0000FFFF); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(F0F0F0F0F0F0F0F0); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(0F0F0F0F0F0F0F0F); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(0123456789ABCDEF); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(FEDCBA9876543210); + DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL(A5A5A5A5A5A5A5A5); + + #undef DO_TEST_EXPAND_UNSIGNED_VALUE_TO_ASCII_IMPL + + } + #endif + }