From a9b30951ce6762353e28e9068af5364778f1fcb2 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 1 Nov 2021 02:52:34 +0200 Subject: [PATCH] lib: Add utility function to convert from hex to binary --- src/lib/base/String.cpp | 56 +++++++++++++++++++++++++ src/lib/base/String.h | 3 ++ src/test/unittests/base/StringTests.cpp | 14 +++++++ 3 files changed, 73 insertions(+) diff --git a/src/lib/base/String.cpp b/src/lib/base/String.cpp index dcf7318a..416b1ec9 100644 --- a/src/lib/base/String.cpp +++ b/src/lib/base/String.cpp @@ -35,6 +35,42 @@ namespace barrier { namespace string { +namespace { + +// returns negative in case of non-matching character +int hex_to_number(char ch) +{ + switch (ch) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; + + case 'A': return 10; + case 'B': return 11; + case 'C': return 12; + case 'D': return 13; + case 'E': return 14; + case 'F': return 15; + } + return -1; +} + +} // namespace + std::string format(const char* fmt, ...) { @@ -196,6 +232,26 @@ std::string to_hex(const std::string& subject, int width, const char fill) return ss.str(); } +std::vector from_hex(const std::string& data) +{ + if ((data.size() % 2) != 0) { + return {}; + } + + std::vector result; + result.reserve(data.size() / 2); + + for (std::size_t i = 0; i < data.size(); i += 2) { + auto high = hex_to_number(data[i]); + auto low = hex_to_number(data[i + 1]); + if (high < 0 || low < 0) { + return {}; + } + result.push_back(high * 16 + low); + } + return result; +} + void uppercase(std::string& subject) { diff --git a/src/lib/base/String.h b/src/lib/base/String.h index a543cf86..4a2e43bf 100644 --- a/src/lib/base/String.h +++ b/src/lib/base/String.h @@ -77,6 +77,9 @@ Convert each character in \c subject into hexdecimal form with \c width */ std::string to_hex(const std::string& subject, int width, const char fill = '0'); +/// Convert binary data from hexadecimal +std::vector from_hex(const std::string& data); + //! Convert to all uppercase /*! Convert each character in \c subject to uppercase diff --git a/src/test/unittests/base/StringTests.cpp b/src/test/unittests/base/StringTests.cpp index fd771f42..c9c4732b 100644 --- a/src/test/unittests/base/StringTests.cpp +++ b/src/test/unittests/base/StringTests.cpp @@ -62,6 +62,20 @@ TEST(StringTests, toHex_plaintext_hexString) EXPECT_EQ("666f6f626172", string::to_hex(subject, width)); } +TEST(StringTests, fromhex_plaintext_string) +{ + auto result = string::from_hex("666f6f626172"); + std::string expected = "foobar"; + EXPECT_EQ(result, std::vector(expected.begin(), expected.end())); +} + +TEST(StringTests, fromhex_binary_string) +{ + auto result = string::from_hex("01020304050600fff9"); + auto expected = std::vector{1, 2, 3, 4, 5, 6, 0, 0xff, 0xf9}; + EXPECT_EQ(result, expected); +} + TEST(StringTests, uppercase_lowercaseInput_uppercaseOutput) { String subject = "12foo3BaR";