util: add printHex() overload that takes a uint64_t

And AsHex helper class.

Change-Id: If6fb6edea258ab281b5ea9cc30deffd2d8994dc5
Refs: #3006
diff --git a/src/util/string-helper.cpp b/src/util/string-helper.cpp
index 3d4ea3f..7665afc 100644
--- a/src/util/string-helper.cpp
+++ b/src/util/string-helper.cpp
@@ -31,6 +31,24 @@
 
 namespace ndn {
 
+std::ostream&
+operator<<(std::ostream& os, const AsHex& hex)
+{
+  printHex(os, hex.m_value, os.flags() & std::ostream::uppercase);
+  return os;
+}
+
+void
+printHex(std::ostream& os, uint64_t num, bool wantUpperCase)
+{
+  auto osFlags = os.flags();
+  // std::showbase doesn't work with number 0
+  os << "0x" << std::noshowbase << std::noshowpos
+     << (wantUpperCase ? std::uppercase : std::nouppercase)
+     << std::hex << num;
+  os.flags(osFlags);
+}
+
 void
 printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase)
 {
diff --git a/src/util/string-helper.hpp b/src/util/string-helper.hpp
index 3f1a303..403c25e 100644
--- a/src/util/string-helper.hpp
+++ b/src/util/string-helper.hpp
@@ -39,17 +39,60 @@
 };
 
 /**
- * @brief Output the hex representation of the bytes in array to the output stream @p os
+ * @brief Helper class to convert a number to hexadecimal
+ *        format, for use with stream insertion operators
+ *
+ * Example usage:
+ *
+ * @code
+ * std::cout << AsHex{42};                   // outputs "0x2a"
+ * std::cout << std::uppercase << AsHex{42}; // outputs "0x2A"
+ * @endcode
+ */
+class AsHex
+{
+public:
+  constexpr explicit
+  AsHex(uint64_t val) noexcept
+    : m_value(val)
+  {
+  }
+
+private:
+  uint64_t m_value;
+
+  friend std::ostream& operator<<(std::ostream&, const AsHex&);
+};
+
+std::ostream&
+operator<<(std::ostream& os, const AsHex& hex);
+
+/**
+ * @brief Output the hex representation of @p num to the output stream @p os
  *
  * @param os Output stream
- * @param buffer The array of bytes
+ * @param num Number to print in hexadecimal format
+ * @param wantUpperCase if true, print uppercase hex chars; the default is to use lowercase
+ *
+ * The output string is a continuous sequence of hex characters without any whitespace separators.
+ */
+void
+printHex(std::ostream& os, uint64_t num, bool wantUpperCase = false);
+
+/**
+ * @brief Output the hex representation of the bytes in @p buffer to the output stream @p os
+ *
+ * @param os Output stream
+ * @param buffer Pointer to an array of bytes
  * @param length Size of the array
- * @param wantUpperCase if true (default) output use uppercase for hex values
+ * @param wantUpperCase if true (the default) print uppercase hex chars
  *
  * Examples:
  *
- *     printHex(std::cout, "Hello, World!") outputs "48656C6C6F2C20776F726C6421"
- *     printHex(std::cout, "Hello, World!", false) outputs "48656c6c6f2c20776f726c6421"
+ * @code
+ * printHex(std::cout, "Hello, World!");        // outputs "48656C6C6F2C20776F726C6421"
+ * printHex(std::cout, "Hello, World!", false); // outputs "48656c6c6f2c20776f726c6421"
+ * @endcode
  *
  * Each octet is always represented as two hex characters ("00" for octet==0).
  *
@@ -59,26 +102,28 @@
 printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase = true);
 
 /**
- * @brief Output the hex representation of the bytes in the @p buffer to the output stream @p os
+ * @brief Output the hex representation of the bytes in @p buffer to the output stream @p os
  *
  * @param os Output stream
- * @param buffer The array of bytes
- * @param wantUpperCase if true (default) output use uppercase for hex values
+ * @param buffer Buffer of bytes to print in hexadecimal format
+ * @param wantUpperCase if true (the default) print uppercase hex chars
  */
 void
 printHex(std::ostream& os, const Buffer& buffer, bool wantUpperCase = true);
 
 /**
- * @brief Return the hex representation of the bytes in array
+ * @brief Return a string containing the hex representation of the bytes in @p buffer
  *
- * @param buffer The array of bytes
+ * @param buffer Pointer to an array of bytes
  * @param length Size of the array
- * @param wantUpperCase if true (default) output use uppercase for hex values
+ * @param wantUpperCase if true (the default) use uppercase hex chars
  *
  * Examples:
  *
- *     toHex("Hello, World!") == "48656C6C6F2C20776F726C6421"
- *     toHex("Hello, World!", false) == "48656c6c6f2c20776f726c6421"
+ * @code
+ * toHex("Hello, World!") == "48656C6C6F2C20776F726C6421"
+ * toHex("Hello, World!", false) == "48656c6c6f2c20776f726c6421"
+ * @endcode
  *
  * Each octet is always represented as two hex characters ("00" for octet==0).
  *
@@ -88,10 +133,10 @@
 toHex(const uint8_t* buffer, size_t length, bool wantUpperCase = true);
 
 /**
- * @brief Return the hex representation of the bytes in the @p buffer to the output stream @p os
+ * @brief Return a string containing the hex representation of the bytes in @p buffer
  *
- * @param buffer The array of bytes
- * @param wantUpperCase if true (default) output use uppercase for hex values
+ * @param buffer Buffer of bytes to convert to hexadecimal format
+ * @param wantUpperCase if true (the default) use uppercase hex chars
  */
 std::string
 toHex(const Buffer& buffer, bool wantUpperCase = true);
@@ -119,8 +164,10 @@
  *
  * Examples:
  *
- *     unescape("hello%20world") == "hello world"
- *     unescape("hello%20world%FooBar") == "hello world%FooBar"
+ * @code
+ * unescape("hello%20world") == "hello world"
+ * unescape("hello%20world%FooBar") == "hello world%FooBar"
+ * @endcode
  */
 std::string
 unescape(const std::string& str);