[PATCH] D90265: [llvm][StringExtras] Add a fail-able version of `fromHex` and optimize hex digit lookup

River Riddle via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 28 10:49:50 PDT 2020


rriddle updated this revision to Diff 301333.
rriddle marked 2 inline comments as done.
rriddle added a comment.

Resolve comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D90265/new/

https://reviews.llvm.org/D90265

Files:
  llvm/include/llvm/ADT/StringExtras.h
  llvm/unittests/ADT/StringExtrasTest.cpp


Index: llvm/unittests/ADT/StringExtrasTest.cpp
===================================================================
--- llvm/unittests/ADT/StringExtrasTest.cpp
+++ llvm/unittests/ADT/StringExtrasTest.cpp
@@ -89,6 +89,10 @@
   EXPECT_EQ(EvenStr, toHex(EvenData));
   EXPECT_EQ(EvenData, fromHex(EvenStr));
   EXPECT_EQ(StringRef(EvenStr).lower(), toHex(EvenData, true));
+
+  std::string InvalidStr = "A5ZX";
+  std::string IgnoredOutput;
+  EXPECT_FALSE(tryGetFromHex(InvalidStr, IgnoredOutput));
 }
 
 TEST(StringExtrasTest, to_float) {
Index: llvm/include/llvm/ADT/StringExtras.h
===================================================================
--- llvm/include/llvm/ADT/StringExtras.h
+++ llvm/include/llvm/ADT/StringExtras.h
@@ -165,34 +165,68 @@
   return toHex(toStringRef(Input), LowerCase);
 }
 
-inline uint8_t hexFromNibbles(char MSB, char LSB) {
+/// Store the binary representation of the two provided values, \p MSB and
+/// \p LSB, that make up the nibbles of a hexadecimal digit. If \p MSB or \p LSB
+/// do not correspond to proper nibbles of a hexadecimal digit, this method
+/// returns false. Otherwise, returns true.
+inline bool tryGetHexFromNibbles(char MSB, char LSB, uint8_t &Hex) {
   unsigned U1 = hexDigitValue(MSB);
   unsigned U2 = hexDigitValue(LSB);
-  assert(U1 != -1U && U2 != -1U);
+  if (U1 == -1U || U2 == -1U)
+    return false;
 
-  return static_cast<uint8_t>((U1 << 4) | U2);
+  Hex = static_cast<uint8_t>((U1 << 4) | U2);
+  return true;
 }
 
-/// Convert hexadecimal string \p Input to its binary representation.
-/// The return string is half the size of \p Input.
-inline std::string fromHex(StringRef Input) {
+/// Return the binary representation of the two provided values, \p MSB and
+/// \p LSB, that make up the nibbles of a hexadecimal digit.
+inline uint8_t hexFromNibbles(char MSB, char LSB) {
+  uint8_t Hex = 0;
+  bool GotHex = tryGetHexFromNibbles(MSB, LSB, Hex);
+  (void)GotHex;
+  assert(GotHex && "MSB and/or LSB do not correspond to hex digits");
+  return Hex;
+}
+
+/// Convert hexadecimal string \p Input to its binary representation and store
+/// the result in \p Output. Returns true if the binary representation could be
+/// converted from the hexadecimal string. Returns false if \p Input contains
+/// non-hexadecimal digits. The output string is half the size of \p Input.
+inline bool tryGetFromHex(StringRef Input, std::string &Output) {
   if (Input.empty())
-    return std::string();
+    return true;
 
-  std::string Output;
   Output.reserve((Input.size() + 1) / 2);
   if (Input.size() % 2 == 1) {
-    Output.push_back(hexFromNibbles('0', Input.front()));
+    uint8_t Hex = 0;
+    if (!tryGetHexFromNibbles('0', Input.front(), Hex))
+      return false;
+
+    Output.push_back(Hex);
     Input = Input.drop_front();
   }
 
   assert(Input.size() % 2 == 0);
   while (!Input.empty()) {
-    uint8_t Hex = hexFromNibbles(Input[0], Input[1]);
+    uint8_t Hex = 0;
+    if (!tryGetHexFromNibbles(Input[0], Input[1], Hex))
+      return false;
+
     Output.push_back(Hex);
     Input = Input.drop_front(2);
   }
-  return Output;
+  return true;
+}
+
+/// Convert hexadecimal string \p Input to its binary representation.
+/// The return string is half the size of \p Input.
+inline std::string fromHex(StringRef Input) {
+  std::string Hex;
+  bool GotHex = tryGetFromHex(Input, Hex);
+  (void)GotHex;
+  assert(GotHex && "Input contains non hex digits");
+  return Hex;
 }
 
 /// Convert the string \p S to an integer of the specified type using


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D90265.301333.patch
Type: text/x-patch
Size: 3533 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201028/1ea4f792/attachment.bin>


More information about the llvm-commits mailing list