return convert<10>(val, buffer);
}
- template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
+ template <typename T, cpp::enable_if_t<cpp::is_integral_v<T> &&
+ (sizeof(T) <= sizeof(uintmax_t)),
+ int> = 0>
LIBC_INLINE static cpp::optional<cpp::string_view>
hex(T val, cpp::span<char> buffer, bool lowercase = true) {
return convert<16>(val, buffer, lowercase);
}
+ template <typename T,
+ cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T> &&
+ (sizeof(T) > sizeof(uintmax_t)) &&
+ sizeof(T) % sizeof(uintmax_t) == 0,
+ int> = 0>
+ LIBC_INLINE static cpp::optional<cpp::string_view>
+ hex(T val, cpp::span<char> buffer, bool lowercase = true) {
+ // We will assume the buffer is exactly sized, which will be the case if
+ // it was sized using the bufsize method.
+ constexpr size_t BLOCKS = sizeof(T) / sizeof(uintmax_t);
+ constexpr size_t UINTMAX_BUFSIZE = bufsize<16, uintmax_t>();
+ // We will zero out the buffer. This specialization is not used to
+ // implement a public function so zeroing out byte-by-byte does not
+ // have any affect on runtime or user expectations.
+ for (size_t i = 0; i < buffer.size(); ++i)
+ buffer[i] = '0';
+ for (size_t i = 0; i < BLOCKS; ++i, val >>= (sizeof(uintmax_t) * 8)) {
+ uintmax_t block_val = static_cast<uintmax_t>(val);
+ hex(block_val,
+ buffer.subspan((BLOCKS - i - 1) * UINTMAX_BUFSIZE, UINTMAX_BUFSIZE),
+ lowercase);
+ }
+ return cpp::string_view(buffer.data(), buffer.size());
+ }
+
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
LIBC_INLINE static cpp::optional<cpp::string_view>
oct(T val, cpp::span<char> buffer) {
//===----------------------------------------------------------------------===//
#include "src/__support/CPP/string_view.h"
+#include "src/__support/UInt.h"
+#include "src/__support/UInt128.h"
#include "src/__support/integer_to_string.h"
#include "test/UnitTest/Test.h"
EXPECT_EQ(*IntegerToString::convert<36>(uint64_t(0xffffffffffffffff), buf),
string_view("3w5e11264sgsf"));
}
+
+TEST(LlvmLibcIntegerToStringTest, UINT128_Base_16) {
+ char buf[IntegerToString::hex_bufsize<UInt128>()];
+ EXPECT_EQ(*IntegerToString::hex(static_cast<UInt128>(0), buf),
+ string_view("00000000000000000000000000000000"));
+ EXPECT_EQ(*IntegerToString::hex(static_cast<UInt128>(0x12345), buf),
+ string_view("00000000000000000000000000012345"));
+ EXPECT_EQ((*IntegerToString::hex(static_cast<UInt128>(0x1234) << 112, buf)),
+ string_view("12340000000000000000000000000000"));
+ EXPECT_EQ((*IntegerToString::hex(static_cast<UInt128>(0x1234) << 48, buf)),
+ string_view("00000000000000001234000000000000"));
+ EXPECT_EQ((*IntegerToString::hex(static_cast<UInt128>(0x1234) << 52, buf)),
+ string_view("00000000000000012340000000000000"));
+}
+
+TEST(LlvmLibcIntegerToStringTest, UINT256_Base_16) {
+ using UInt256 = __llvm_libc::cpp::UInt<256>;
+ char buf[IntegerToString::hex_bufsize<UInt256>()];
+ EXPECT_EQ(
+ *IntegerToString::hex(static_cast<UInt256>(0), buf),
+ string_view(
+ "0000000000000000000000000000000000000000000000000000000000000000"));
+ EXPECT_EQ(
+ *IntegerToString::hex(static_cast<UInt256>(0x12345), buf),
+ string_view(
+ "0000000000000000000000000000000000000000000000000000000000012345"));
+ EXPECT_EQ(
+ (*IntegerToString::hex(static_cast<UInt256>(0x1234) << 112, buf)),
+ string_view(
+ "0000000000000000000000000000000012340000000000000000000000000000"));
+ EXPECT_EQ(
+ (*IntegerToString::hex(static_cast<UInt256>(0x1234) << 116, buf)),
+ string_view(
+ "0000000000000000000000000000000123400000000000000000000000000000"));
+ EXPECT_EQ(
+ (*IntegerToString::hex(static_cast<UInt256>(0x1234) << 240, buf)),
+ string_view(
+ "1234000000000000000000000000000000000000000000000000000000000000"));
+}