From e46b4498b8f11925986704196094eb6a89f6e3dc Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 25 Apr 2017 20:21:35 +0000 Subject: [PATCH] [StringExtras] Add a fromHex to complement toHex. We already have a function toHex that will convert a string like "\xFF\xFF" to the string "FFFF", but we do not have one that goes the other way - i.e. to convert a textual string representing a sequence of hexadecimal characters into the corresponding actual bytes. This patch adds such a function. llvm-svn: 301356 --- llvm/include/llvm/ADT/StringExtras.h | 30 ++++++++++++++++++++++++++++++ llvm/unittests/ADT/StringExtrasTest.cpp | 16 ++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h index 8214782..26f1192 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/include/llvm/ADT/StringExtras.h @@ -76,6 +76,36 @@ static inline std::string toHex(StringRef Input) { return Output; } +static inline uint8_t hexFromNibbles(char MSB, char LSB) { + unsigned U1 = hexDigitValue(MSB); + unsigned U2 = hexDigitValue(LSB); + assert(U1 != -1U && U2 != -1U); + + return static_cast((U1 << 4) | U2); +} + +/// Convert hexadecimal string \p Input to its binary representation. +/// The return string is half the size of \p Input. +static inline std::string fromHex(StringRef Input) { + if (Input.empty()) + return std::string(); + + std::string Output; + Output.reserve((Input.size() + 1) / 2); + if (Input.size() % 2 == 1) { + Output.push_back(hexFromNibbles('0', Input.front())); + Input = Input.drop_front(); + } + + assert(Input.size() % 2 == 0); + while (!Input.empty()) { + uint8_t Hex = hexFromNibbles(Input[0], Input[1]); + Output.push_back(Hex); + Input = Input.drop_front(2); + } + return Output; +} + static inline std::string utostr(uint64_t X, bool isNeg = false) { char Buffer[21]; char *BufPtr = std::end(Buffer); diff --git a/llvm/unittests/ADT/StringExtrasTest.cpp b/llvm/unittests/ADT/StringExtrasTest.cpp index afb984e..2cc9cad 100644 --- a/llvm/unittests/ADT/StringExtrasTest.cpp +++ b/llvm/unittests/ADT/StringExtrasTest.cpp @@ -50,3 +50,19 @@ TEST(StringExtrasTest, JoinItems) { EXPECT_EQ("foo/bar/baz/x", join_items('/', Foo, Bar, Baz, X)); } + +TEST(StringExtrasTest, ToAndFromHex) { + std::vector OddBytes = {0x5, 0xBD, 0x0D, 0x3E, 0xCD}; + std::string OddStr = "05BD0D3ECD"; + StringRef OddData(reinterpret_cast(OddBytes.data()), + OddBytes.size()); + EXPECT_EQ(OddStr, toHex(OddData)); + EXPECT_EQ(OddData, fromHex(StringRef(OddStr).drop_front())); + + std::vector EvenBytes = {0xA5, 0xBD, 0x0D, 0x3E, 0xCD}; + std::string EvenStr = "A5BD0D3ECD"; + StringRef EvenData(reinterpret_cast(EvenBytes.data()), + EvenBytes.size()); + EXPECT_EQ(EvenStr, toHex(EvenData)); + EXPECT_EQ(EvenData, fromHex(EvenStr)); +} \ No newline at end of file -- 2.7.4