[libc-commits] [libc] 625d692 - [libc] Extend IntegerToString to convert UInt* numbers to hex string.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Thu May 18 09:44:53 PDT 2023


Author: Siva Chandra Reddy
Date: 2023-05-18T16:44:43Z
New Revision: 625d6928a863cdc60a907d5fcaf03dee60d25c8a

URL: https://github.com/llvm/llvm-project/commit/625d6928a863cdc60a907d5fcaf03dee60d25c8a
DIFF: https://github.com/llvm/llvm-project/commit/625d6928a863cdc60a907d5fcaf03dee60d25c8a.diff

LOG: [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

Added: 
    

Modified: 
    libc/src/__support/integer_to_string.h
    libc/test/src/__support/CMakeLists.txt
    libc/test/src/__support/integer_to_string_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/integer_to_string.h b/libc/src/__support/integer_to_string.h
index a748575ab0ad5..22c5acee56e65 100644
--- a/libc/src/__support/integer_to_string.h
+++ b/libc/src/__support/integer_to_string.h
@@ -157,12 +157,39 @@ class IntegerToString {
     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) {

diff  --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt
index 7390ed2471f72..154ebfe307e97 100644
--- a/libc/test/src/__support/CMakeLists.txt
+++ b/libc/test/src/__support/CMakeLists.txt
@@ -55,6 +55,8 @@ add_libc_test(
   DEPENDS
     libc.src.__support.integer_to_string
     libc.src.__support.CPP.string_view
+    libc.src.__support.uint
+    libc.src.__support.uint128
 )
 
 # The GPU does not support varargs currently.

diff  --git a/libc/test/src/__support/integer_to_string_test.cpp b/libc/test/src/__support/integer_to_string_test.cpp
index 26d9f6b1afcb0..783a4d8082690 100644
--- a/libc/test/src/__support/integer_to_string_test.cpp
+++ b/libc/test/src/__support/integer_to_string_test.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #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"
@@ -247,3 +249,42 @@ TEST(LlvmLibcIntegerToStringTest, UINT64_Base_36) {
   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"));
+}


        


More information about the libc-commits mailing list