util: add printHex() overload that takes a uint64_t
And AsHex helper class.
Change-Id: If6fb6edea258ab281b5ea9cc30deffd2d8994dc5
Refs: #3006
diff --git a/src/encoding/nfd-constants.cpp b/src/encoding/nfd-constants.cpp
index c1c8060..2b9f8ff 100644
--- a/src/encoding/nfd-constants.cpp
+++ b/src/encoding/nfd-constants.cpp
@@ -20,9 +20,10 @@
*/
#include "nfd-constants.hpp"
+#include "util/string-helper.hpp"
-#include <iostream>
#include <map>
+#include <ostream>
namespace ndn {
namespace nfd {
@@ -137,20 +138,17 @@
std::string token;
std::tie(bit, token) = pair;
- if ((routeFlags & bit) == 0) {
- continue;
+ if ((routeFlags & bit) != 0) {
+ printToken(token);
+ routeFlags = static_cast<RouteFlags>(routeFlags & ~bit);
}
-
- printToken(token);
- routeFlags = static_cast<RouteFlags>(routeFlags & ~bit);
}
- if (routeFlags != 0) {
- printToken("0x");
- std::ios_base::fmtflags oldFmt = os.flags();
- os << std::hex << std::nouppercase
- << static_cast<uint64_t>(routeFlags);
- os.flags(oldFmt);
+ if (routeFlags != ROUTE_FLAGS_NONE) {
+ if (!isFirst) {
+ os << '|';
+ }
+ os << AsHex{routeFlags};
}
return os;
diff --git a/src/mgmt/nfd/control-parameters.cpp b/src/mgmt/nfd/control-parameters.cpp
index 30f8fe9..4958749 100644
--- a/src/mgmt/nfd/control-parameters.cpp
+++ b/src/mgmt/nfd/control-parameters.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -23,6 +23,7 @@
#include "encoding/tlv-nfd.hpp"
#include "encoding/block-helpers.hpp"
#include "util/concepts.hpp"
+#include "util/string-helper.hpp"
namespace ndn {
namespace nfd {
@@ -304,15 +305,11 @@
}
if (parameters.hasFlags()) {
- std::ios_base::fmtflags osFlags = os.flags();
- os << "Flags: " << std::showbase << std::hex << parameters.getFlags() << ", ";
- os.flags(osFlags);
+ os << "Flags: " << AsHex{parameters.getFlags()} << ", ";
}
if (parameters.hasMask()) {
- std::ios_base::fmtflags osFlags = os.flags();
- os << "Mask: " << std::showbase << std::hex << parameters.getMask() << ", ";
- os.flags(osFlags);
+ os << "Mask: " << AsHex{parameters.getMask()} << ", ";
}
if (parameters.hasStrategy()) {
diff --git a/src/mgmt/nfd/face-event-notification.cpp b/src/mgmt/nfd/face-event-notification.cpp
index 505026b..888fe61 100644
--- a/src/mgmt/nfd/face-event-notification.cpp
+++ b/src/mgmt/nfd/face-event-notification.cpp
@@ -24,8 +24,7 @@
#include "encoding/encoding-buffer.hpp"
#include "encoding/tlv-nfd.hpp"
#include "util/concepts.hpp"
-
-#include <iomanip>
+#include "util/string-helper.hpp"
namespace ndn {
namespace nfd {
@@ -197,13 +196,8 @@
<< " LocalUri: " << notification.getLocalUri() << ",\n"
<< " FaceScope: " << notification.getFaceScope() << ",\n"
<< " FacePersistency: " << notification.getFacePersistency() << ",\n"
- << " LinkType: " << notification.getLinkType() << ",\n";
-
- auto osFlags = os.flags();
- // std::showbase doesn't work with number 0
- os << " Flags: 0x" << std::noshowbase << std::noshowpos << std::nouppercase
- << std::hex << notification.getFlags() << "\n";
- os.flags(osFlags);
+ << " LinkType: " << notification.getLinkType() << ",\n"
+ << " Flags: " << AsHex{notification.getFlags()} << "\n";
return os << " )";
}
diff --git a/src/mgmt/nfd/face-status.cpp b/src/mgmt/nfd/face-status.cpp
index ea0d546..df0521f 100644
--- a/src/mgmt/nfd/face-status.cpp
+++ b/src/mgmt/nfd/face-status.cpp
@@ -24,8 +24,7 @@
#include "encoding/encoding-buffer.hpp"
#include "encoding/tlv-nfd.hpp"
#include "util/concepts.hpp"
-
-#include <iomanip>
+#include "util/string-helper.hpp"
namespace ndn {
namespace nfd {
@@ -366,15 +365,9 @@
os << " FaceScope: " << status.getFaceScope() << ",\n"
<< " FacePersistency: " << status.getFacePersistency() << ",\n"
- << " LinkType: " << status.getLinkType() << ",\n";
-
- auto osFlags = os.flags();
- // std::showbase doesn't work with number 0
- os << " Flags: 0x" << std::noshowbase << std::noshowpos << std::nouppercase
- << std::hex << status.getFlags() << ",\n";
- os.flags(osFlags);
-
- os << " Counters: {Interests: {in: " << status.getNInInterests() << ", "
+ << " LinkType: " << status.getLinkType() << ",\n"
+ << " Flags: " << AsHex{status.getFlags()} << ",\n"
+ << " Counters: {Interests: {in: " << status.getNInInterests() << ", "
<< "out: " << status.getNOutInterests() << "},\n"
<< " Data: {in: " << status.getNInDatas() << ", "
<< "out: " << status.getNOutDatas() << "},\n"
diff --git a/src/mgmt/nfd/rib-entry.cpp b/src/mgmt/nfd/rib-entry.cpp
index 17b53d6..c7ec47a 100644
--- a/src/mgmt/nfd/rib-entry.cpp
+++ b/src/mgmt/nfd/rib-entry.cpp
@@ -24,6 +24,7 @@
#include "encoding/encoding-buffer.hpp"
#include "encoding/tlv-nfd.hpp"
#include "util/concepts.hpp"
+#include "util/string-helper.hpp"
#include <boost/range/adaptor/reversed.hpp>
@@ -206,13 +207,8 @@
os << "Route("
<< "FaceId: " << route.getFaceId() << ", "
<< "Origin: " << route.getOrigin() << ", "
- << "Cost: " << route.getCost() << ", ";
-
- auto osFlags = os.flags();
- // std::showbase doesn't work with number 0
- os << "Flags: 0x" << std::noshowbase << std::noshowpos << std::nouppercase
- << std::hex << route.getFlags() << ", ";
- os.flags(osFlags);
+ << "Cost: " << route.getCost() << ", "
+ << "Flags: " << AsHex{route.getFlags()} << ", ";
if (route.hasExpirationPeriod()) {
os << "ExpirationPeriod: " << route.getExpirationPeriod();
diff --git a/src/name-component.cpp b/src/name-component.cpp
index 13005dd..746f69a 100644
--- a/src/name-component.cpp
+++ b/src/name-component.cpp
@@ -104,7 +104,7 @@
trimmedString.erase(0, getSha256DigestUriPrefix().size());
return fromImplicitSha256Digest(fromHex(trimmedString));
}
- catch (StringHelperError& e) {
+ catch (const StringHelperError&) {
BOOST_THROW_EXCEPTION(Error("Cannot convert to a ImplicitSha256DigestComponent (invalid hex "
"encoding)"));
}
@@ -154,7 +154,7 @@
}
else {
// In case we need to escape, set to upper case hex and save the previous flags.
- std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
+ auto savedFlags = result.flags(std::ios::hex | std::ios::uppercase);
for (size_t i = 0; i < valueSize; ++i) {
uint8_t x = value[i];
@@ -172,7 +172,7 @@
}
// Restore.
- result.flags(saveFlags);
+ result.flags(savedFlags);
}
}
}
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);
diff --git a/tests/unit-tests/name.t.cpp b/tests/unit-tests/name.t.cpp
index a49a9c4..9840196 100644
--- a/tests/unit-tests/name.t.cpp
+++ b/tests/unit-tests/name.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -67,28 +67,19 @@
BOOST_AUTO_TEST_CASE(Encode)
{
Name name("/local/ndn/prefix");
+ const Block& wire = name.wireEncode();
- const Block &wire = name.wireEncode();
-
- // for (Buffer::const_iterator i = wire.begin();
- // i != wire.end();
- // ++i)
- // {
- // std::ios::fmtflags saveFlags = std::cout.flags(std::ios::hex);
-
- // if (i != wire.begin())
- // std::cout << ", ";
- // std::cout << "0x" << static_cast<uint32_t>(*i);
-
- // std::cout.flags(saveFlags);
- // }
+ // for (auto i = wire.begin(); i != wire.end(); ++i) {
+ // if (i != wire.begin())
+ // std::cout << ", ";
+ // printHex(std::cout, *i);
+ // }
// std::cout << std::endl;
- BOOST_CHECK_EQUAL_COLLECTIONS(TestName, TestName+sizeof(TestName),
+ BOOST_CHECK_EQUAL_COLLECTIONS(TestName, TestName + sizeof(TestName),
wire.begin(), wire.end());
}
-
BOOST_AUTO_TEST_CASE(Decode)
{
Block block(TestName, sizeof(TestName));
diff --git a/tests/unit-tests/util/string-helper.t.cpp b/tests/unit-tests/util/string-helper.t.cpp
index c5cc218..64144f8 100644
--- a/tests/unit-tests/util/string-helper.t.cpp
+++ b/tests/unit-tests/util/string-helper.t.cpp
@@ -31,6 +31,47 @@
BOOST_AUTO_TEST_SUITE(Util)
BOOST_AUTO_TEST_SUITE(TestStringHelper)
+BOOST_AUTO_TEST_CASE(PrintHex)
+{
+ boost::test_tools::output_test_stream os;
+
+ printHex(os, 0);
+ BOOST_CHECK(os.is_equal("0x0"));
+
+ printHex(os, 42);
+ BOOST_CHECK(os.is_equal("0x2a"));
+
+ printHex(os, 2748, true);
+ BOOST_CHECK(os.is_equal("0xABC"));
+
+ printHex(os, static_cast<uint64_t>(-1));
+ BOOST_CHECK(os.is_equal("0xffffffffffffffff"));
+
+ printHex(os, ~0U, true);
+ BOOST_CHECK(os.is_equal("0xFFFFFFFF"));
+
+ printHex(os, ~0ULL, true);
+ BOOST_CHECK(os.is_equal("0xFFFFFFFFFFFFFFFF"));
+}
+
+BOOST_AUTO_TEST_CASE(AsHex)
+{
+ using ndn::AsHex;
+ boost::test_tools::output_test_stream os;
+
+ os << AsHex{0};
+ BOOST_CHECK(os.is_equal("0x0"));
+
+ os << AsHex{42};
+ BOOST_CHECK(os.is_equal("0x2a"));
+
+ os << std::uppercase << AsHex{~0U};
+ BOOST_CHECK(os.is_equal("0xFFFFFFFF"));
+
+ os << std::nouppercase << AsHex{~0U};
+ BOOST_CHECK(os.is_equal("0xffffffff"));
+}
+
BOOST_AUTO_TEST_CASE(ToHex)
{
std::string test = "Hello, world!";