Skip to content

Commit 625d692

Browse files
author
Siva Chandra Reddy
committed
[libc] Extend IntegerToString to convert UInt* numbers to hex string.
This new functionality will help us avoid duplicated code in various places in the testing infrastructure. Since the string representation of the wide numbers is to be used by tests, to keep it simple, we zero-pad the strings. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D150849
1 parent db81455 commit 625d692

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

libc/src/__support/integer_to_string.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,39 @@ class IntegerToString {
157157
return convert<10>(val, buffer);
158158
}
159159

160-
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
160+
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T> &&
161+
(sizeof(T) <= sizeof(uintmax_t)),
162+
int> = 0>
161163
LIBC_INLINE static cpp::optional<cpp::string_view>
162164
hex(T val, cpp::span<char> buffer, bool lowercase = true) {
163165
return convert<16>(val, buffer, lowercase);
164166
}
165167

168+
template <typename T,
169+
cpp::enable_if_t<cpp::is_integral_v<T> && cpp::is_unsigned_v<T> &&
170+
(sizeof(T) > sizeof(uintmax_t)) &&
171+
sizeof(T) % sizeof(uintmax_t) == 0,
172+
int> = 0>
173+
LIBC_INLINE static cpp::optional<cpp::string_view>
174+
hex(T val, cpp::span<char> buffer, bool lowercase = true) {
175+
// We will assume the buffer is exactly sized, which will be the case if
176+
// it was sized using the bufsize method.
177+
constexpr size_t BLOCKS = sizeof(T) / sizeof(uintmax_t);
178+
constexpr size_t UINTMAX_BUFSIZE = bufsize<16, uintmax_t>();
179+
// We will zero out the buffer. This specialization is not used to
180+
// implement a public function so zeroing out byte-by-byte does not
181+
// have any affect on runtime or user expectations.
182+
for (size_t i = 0; i < buffer.size(); ++i)
183+
buffer[i] = '0';
184+
for (size_t i = 0; i < BLOCKS; ++i, val >>= (sizeof(uintmax_t) * 8)) {
185+
uintmax_t block_val = static_cast<uintmax_t>(val);
186+
hex(block_val,
187+
buffer.subspan((BLOCKS - i - 1) * UINTMAX_BUFSIZE, UINTMAX_BUFSIZE),
188+
lowercase);
189+
}
190+
return cpp::string_view(buffer.data(), buffer.size());
191+
}
192+
166193
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
167194
LIBC_INLINE static cpp::optional<cpp::string_view>
168195
oct(T val, cpp::span<char> buffer) {

libc/test/src/__support/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ add_libc_test(
5555
DEPENDS
5656
libc.src.__support.integer_to_string
5757
libc.src.__support.CPP.string_view
58+
libc.src.__support.uint
59+
libc.src.__support.uint128
5860
)
5961

6062
# The GPU does not support varargs currently.

libc/test/src/__support/integer_to_string_test.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/__support/CPP/string_view.h"
10+
#include "src/__support/UInt.h"
11+
#include "src/__support/UInt128.h"
1012
#include "src/__support/integer_to_string.h"
1113

1214
#include "test/UnitTest/Test.h"
@@ -247,3 +249,42 @@ TEST(LlvmLibcIntegerToStringTest, UINT64_Base_36) {
247249
EXPECT_EQ(*IntegerToString::convert<36>(uint64_t(0xffffffffffffffff), buf),
248250
string_view("3w5e11264sgsf"));
249251
}
252+
253+
TEST(LlvmLibcIntegerToStringTest, UINT128_Base_16) {
254+
char buf[IntegerToString::hex_bufsize<UInt128>()];
255+
EXPECT_EQ(*IntegerToString::hex(static_cast<UInt128>(0), buf),
256+
string_view("00000000000000000000000000000000"));
257+
EXPECT_EQ(*IntegerToString::hex(static_cast<UInt128>(0x12345), buf),
258+
string_view("00000000000000000000000000012345"));
259+
EXPECT_EQ((*IntegerToString::hex(static_cast<UInt128>(0x1234) << 112, buf)),
260+
string_view("12340000000000000000000000000000"));
261+
EXPECT_EQ((*IntegerToString::hex(static_cast<UInt128>(0x1234) << 48, buf)),
262+
string_view("00000000000000001234000000000000"));
263+
EXPECT_EQ((*IntegerToString::hex(static_cast<UInt128>(0x1234) << 52, buf)),
264+
string_view("00000000000000012340000000000000"));
265+
}
266+
267+
TEST(LlvmLibcIntegerToStringTest, UINT256_Base_16) {
268+
using UInt256 = __llvm_libc::cpp::UInt<256>;
269+
char buf[IntegerToString::hex_bufsize<UInt256>()];
270+
EXPECT_EQ(
271+
*IntegerToString::hex(static_cast<UInt256>(0), buf),
272+
string_view(
273+
"0000000000000000000000000000000000000000000000000000000000000000"));
274+
EXPECT_EQ(
275+
*IntegerToString::hex(static_cast<UInt256>(0x12345), buf),
276+
string_view(
277+
"0000000000000000000000000000000000000000000000000000000000012345"));
278+
EXPECT_EQ(
279+
(*IntegerToString::hex(static_cast<UInt256>(0x1234) << 112, buf)),
280+
string_view(
281+
"0000000000000000000000000000000012340000000000000000000000000000"));
282+
EXPECT_EQ(
283+
(*IntegerToString::hex(static_cast<UInt256>(0x1234) << 116, buf)),
284+
string_view(
285+
"0000000000000000000000000000000123400000000000000000000000000000"));
286+
EXPECT_EQ(
287+
(*IntegerToString::hex(static_cast<UInt256>(0x1234) << 240, buf)),
288+
string_view(
289+
"1234000000000000000000000000000000000000000000000000000000000000"));
290+
}

0 commit comments

Comments
 (0)