add hexlify() and unhexlify() convenience methods
authorAdam Simpkins <simpkins@fb.com>
Wed, 8 Jun 2016 19:49:45 +0000 (12:49 -0700)
committerFacebook Github Bot 8 <facebook-github-bot-8-bot@fb.com>
Wed, 8 Jun 2016 19:53:27 +0000 (12:53 -0700)
Summary:
Add new versions of hexlify() and unhexlify() that directly return a
std::string, similar to the helper functions that already exist for humanify()
and backslashify().

The function signatures for these helpers are different than the humanify() and
backslashify() helpers--these functions always accept StringPiece or ByteRange
arguments.  This allows them to easily accept "const char*" arguments, without
having to convert the arguments to a std::string.  (I think we probably should
fix the humanify() and backslashify() helpers to be similar in a separate
diff.)

Reviewed By: yfeldblum

Differential Revision: D3403863

fbshipit-source-id: a2df49d5857e1d34caac3d78283dc293f4ef1ab6

folly/String.h
folly/test/StringTest.cpp

index ba43160d5606609559d123dcda5a847d3cbb6a91..d900e7850c0c340a0d9dad4e10cae52b2401b9ea 100644 (file)
@@ -259,6 +259,21 @@ template<class InputString, class OutputString>
 bool hexlify(const InputString& input, OutputString& output,
              bool append=false);
 
+template <class OutputString = std::string>
+OutputString hexlify(ByteRange input) {
+  OutputString output;
+  if (!hexlify(input, output)) {
+    // hexlify() currently always returns true, so this can't really happen
+    throw std::runtime_error("hexlify failed");
+  }
+  return output;
+}
+
+template <class OutputString = std::string>
+OutputString hexlify(StringPiece input) {
+  return hexlify<OutputString>(ByteRange{input});
+}
+
 /**
  * Same functionality as Python's binascii.unhexlify.  Returns true
  * on successful conversion.
@@ -266,6 +281,17 @@ bool hexlify(const InputString& input, OutputString& output,
 template<class InputString, class OutputString>
 bool unhexlify(const InputString& input, OutputString& output);
 
+template <class OutputString = std::string>
+OutputString unhexlify(StringPiece input) {
+  OutputString output;
+  if (!unhexlify(input, output)) {
+    // unhexlify() fails if the input has non-hexidecimal characters,
+    // or if it doesn't consist of a whole number of bytes
+    throw std::domain_error("unhexlify() called with non-hex input");
+  }
+  return output;
+}
+
 /*
  * A pretty-printer for numbers that appends suffixes of units of the
  * given type.  It prints 4 sig-figs of value with the most
index 467141efddee65da4ab3786b82be6773ecbca781..5e22294fe9b8e1e9b63f0040aec139976384286a 100644 (file)
@@ -19,6 +19,8 @@
 #include <boost/regex.hpp>
 #include <gtest/gtest.h>
 
+#include <folly/Array.h>
+
 using namespace folly;
 using namespace std;
 
@@ -972,7 +974,7 @@ TEST(String, hexlify) {
   string input1 = "0123";
   string output1;
   EXPECT_TRUE(hexlify(input1, output1));
-  EXPECT_EQ(output1, "30313233");
+  EXPECT_EQ("30313233", output1);
 
   fbstring input2 = "abcdefg";
   input2[1] = 0;
@@ -980,7 +982,11 @@ TEST(String, hexlify) {
   input2[5] = 0xb6;
   fbstring output2;
   EXPECT_TRUE(hexlify(input2, output2));
-  EXPECT_EQ(output2, "610063ff65b667");
+  EXPECT_EQ("610063ff65b667", output2);
+
+  EXPECT_EQ("666f6f626172", hexlify("foobar"));
+  auto bytes = folly::make_array<uint8_t>(1, 2, 3, 4);
+  EXPECT_EQ("01020304", hexlify(ByteRange{bytes.data(), bytes.size()}));
 }
 
 TEST(String, unhexlify) {
@@ -1008,6 +1014,10 @@ TEST(String, unhexlify) {
   string input4 = "xy";
   string output4;
   EXPECT_FALSE(unhexlify(input4, output4));
+
+  EXPECT_EQ("foobar", unhexlify("666f6f626172"));
+  EXPECT_EQ(StringPiece("foo\0bar", 7), unhexlify("666f6f00626172"));
+  EXPECT_THROW(unhexlify("666f6fzz626172"), std::domain_error);
 }
 
 TEST(String, backslashify) {