mgmt: add FaceQueryFilter::empty()

This commit also simplifies FaceQueryFilter with ndn::optional.

refs #3864

Change-Id: I7cd52101b83ca88df499ca4b507ce93ef6269fd4
diff --git a/src/mgmt/nfd/face-query-filter.cpp b/src/mgmt/nfd/face-query-filter.cpp
index 904baa4..36a1206 100644
--- a/src/mgmt/nfd/face-query-filter.cpp
+++ b/src/mgmt/nfd/face-query-filter.cpp
@@ -33,16 +33,7 @@
 static_assert(std::is_base_of<tlv::Error, FaceQueryFilter::Error>::value,
               "FaceQueryFilter::Error must inherit from tlv::Error");
 
-FaceQueryFilter::FaceQueryFilter()
-  : m_hasFaceId(false)
-  , m_hasUriScheme(false)
-  , m_hasRemoteUri(false)
-  , m_hasLocalUri(false)
-  , m_hasFaceScope(false)
-  , m_hasFacePersistency(false)
-  , m_hasLinkType(false)
-{
-}
+FaceQueryFilter::FaceQueryFilter() = default;
 
 FaceQueryFilter::FaceQueryFilter(const Block& block)
 {
@@ -55,39 +46,39 @@
 {
   size_t totalLength = 0;
 
-  if (m_hasLinkType) {
+  if (m_linkType) {
     totalLength += prependNonNegativeIntegerBlock(encoder,
-                   tlv::nfd::LinkType, m_linkType);
+                   tlv::nfd::LinkType, *m_linkType);
   }
 
-  if (m_hasFacePersistency) {
+  if (m_facePersistency) {
     totalLength += prependNonNegativeIntegerBlock(encoder,
-                   tlv::nfd::FacePersistency, m_facePersistency);
+                   tlv::nfd::FacePersistency, *m_facePersistency);
   }
 
-  if (m_hasFaceScope) {
+  if (m_faceScope) {
     totalLength += prependNonNegativeIntegerBlock(encoder,
-                   tlv::nfd::FaceScope, m_faceScope);
+                   tlv::nfd::FaceScope, *m_faceScope);
   }
 
-  if (m_hasLocalUri) {
+  if (hasLocalUri()) {
     totalLength += encoder.prependByteArrayBlock(tlv::nfd::LocalUri,
-                   reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+                   reinterpret_cast<const uint8_t*>(m_localUri.data()), m_localUri.size());
   }
 
-  if (m_hasRemoteUri) {
+  if (hasRemoteUri()) {
     totalLength += encoder.prependByteArrayBlock(tlv::nfd::Uri,
-                   reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
+                   reinterpret_cast<const uint8_t*>(m_remoteUri.data()), m_remoteUri.size());
   }
 
-  if (m_hasUriScheme) {
+  if (hasUriScheme()) {
     totalLength += encoder.prependByteArrayBlock(tlv::nfd::UriScheme,
-                   reinterpret_cast<const uint8_t*>(m_uriScheme.c_str()), m_uriScheme.size());
+                   reinterpret_cast<const uint8_t*>(m_uriScheme.data()), m_uriScheme.size());
   }
 
-  if (m_hasFaceId) {
+  if (m_faceId) {
     totalLength += prependNonNegativeIntegerBlock(encoder,
-                   tlv::nfd::FaceId, m_faceId);
+                   tlv::nfd::FaceId, *m_faceId);
   }
 
   totalLength += encoder.prependVarNumber(totalLength);
@@ -120,7 +111,7 @@
 void
 FaceQueryFilter::wireDecode(const Block& block)
 {
-  //all fields are optional
+  // all fields are optional
   if (block.type() != tlv::nfd::FaceQueryFilter) {
     BOOST_THROW_EXCEPTION(Error("expecting FaceQueryFilter block"));
   }
@@ -131,67 +122,71 @@
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
     m_faceId = readNonNegativeInteger(*val);
-    m_hasFaceId = true;
     ++val;
   }
   else {
-    m_hasFaceId = false;
+    m_faceId = nullopt;
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::UriScheme) {
     m_uriScheme.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
-    m_hasUriScheme = true;
     ++val;
   }
   else {
-    m_hasUriScheme = false;
+    m_uriScheme.clear();
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
     m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
-    m_hasRemoteUri = true;
     ++val;
   }
   else {
-    m_hasRemoteUri = false;
+    m_remoteUri.clear();
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
     m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
-    m_hasLocalUri = true;
     ++val;
   }
   else {
-    m_hasLocalUri = false;
+    m_localUri.clear();
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
     m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
-    m_hasFaceScope = true;
     ++val;
   }
   else {
-    m_hasFaceScope = false;
+    m_faceScope = nullopt;
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
     m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
-    m_hasFacePersistency = true;
     ++val;
   }
   else {
-    m_hasFacePersistency = false;
+    m_facePersistency = nullopt;
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
     m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
-    m_hasLinkType = true;
     ++val;
   }
   else {
-    m_hasLinkType = false;
+    m_linkType = nullopt;
   }
+}
 
+bool
+FaceQueryFilter::empty() const
+{
+  return !this->hasFaceId() &&
+         !this->hasUriScheme() &&
+         !this->hasRemoteUri() &&
+         !this->hasLocalUri() &&
+         !this->hasFaceScope() &&
+         !this->hasFacePersistency() &&
+         !this->hasLinkType();
 }
 
 FaceQueryFilter&
@@ -199,7 +194,6 @@
 {
   m_wire.reset();
   m_faceId = faceId;
-  m_hasFaceId = true;
   return *this;
 }
 
@@ -207,7 +201,7 @@
 FaceQueryFilter::unsetFaceId()
 {
   m_wire.reset();
-  m_hasFaceId = false;
+  m_faceId = nullopt;
   return *this;
 }
 
@@ -216,16 +210,13 @@
 {
   m_wire.reset();
   m_uriScheme = uriScheme;
-  m_hasUriScheme = true;
   return *this;
 }
 
 FaceQueryFilter&
 FaceQueryFilter::unsetUriScheme()
 {
-  m_wire.reset();
-  m_hasUriScheme = false;
-  return *this;
+  return this->setUriScheme("");
 }
 
 FaceQueryFilter&
@@ -233,16 +224,13 @@
 {
   m_wire.reset();
   m_remoteUri = remoteUri;
-  m_hasRemoteUri = true;
   return *this;
 }
 
 FaceQueryFilter&
 FaceQueryFilter::unsetRemoteUri()
 {
-  m_wire.reset();
-  m_hasRemoteUri = false;
-  return *this;
+  return this->setRemoteUri("");
 }
 
 FaceQueryFilter&
@@ -250,16 +238,13 @@
 {
   m_wire.reset();
   m_localUri = localUri;
-  m_hasLocalUri = true;
   return *this;
 }
 
 FaceQueryFilter&
 FaceQueryFilter::unsetLocalUri()
 {
-  m_wire.reset();
-  m_hasLocalUri = false;
-  return *this;
+  return this->setLocalUri("");
 }
 
 FaceQueryFilter&
@@ -267,7 +252,6 @@
 {
   m_wire.reset();
   m_faceScope = faceScope;
-  m_hasFaceScope = true;
   return *this;
 }
 
@@ -275,7 +259,7 @@
 FaceQueryFilter::unsetFaceScope()
 {
   m_wire.reset();
-  m_hasFaceScope = false;
+  m_faceScope = nullopt;
   return *this;
 }
 
@@ -284,7 +268,6 @@
 {
   m_wire.reset();
   m_facePersistency = facePersistency;
-  m_hasFacePersistency = true;
   return *this;
 }
 
@@ -292,7 +275,7 @@
 FaceQueryFilter::unsetFacePersistency()
 {
   m_wire.reset();
-  m_hasFacePersistency = false;
+  m_facePersistency = nullopt;
   return *this;
 }
 
@@ -301,7 +284,6 @@
 {
   m_wire.reset();
   m_linkType = linkType;
-  m_hasLinkType = true;
   return *this;
 }
 
@@ -309,7 +291,7 @@
 FaceQueryFilter::unsetLinkType()
 {
   m_wire.reset();
-  m_hasLinkType = false;
+  m_linkType = nullopt;
   return *this;
 }
 
diff --git a/src/mgmt/nfd/face-query-filter.hpp b/src/mgmt/nfd/face-query-filter.hpp
index 9ed1226..a7831a5 100644
--- a/src/mgmt/nfd/face-query-filter.hpp
+++ b/src/mgmt/nfd/face-query-filter.hpp
@@ -67,19 +67,23 @@
   void
   wireDecode(const Block& wire);
 
-public: // getters & setters
+  /** \return whether the filter is empty
+   */
+  bool
+  empty() const;
 
+public: // getters & setters
   bool
   hasFaceId() const
   {
-    return m_hasFaceId;
+    return !!m_faceId;
   }
 
   uint64_t
   getFaceId() const
   {
     BOOST_ASSERT(this->hasFaceId());
-    return m_faceId;
+    return *m_faceId;
   }
 
   FaceQueryFilter&
@@ -91,7 +95,7 @@
   bool
   hasUriScheme() const
   {
-    return m_hasUriScheme;
+    return !m_uriScheme.empty();
   }
 
   const std::string&
@@ -110,7 +114,7 @@
   bool
   hasRemoteUri() const
   {
-    return m_hasRemoteUri;
+    return !m_remoteUri.empty();
   }
 
   const std::string&
@@ -129,7 +133,7 @@
   bool
   hasLocalUri() const
   {
-    return m_hasLocalUri;
+    return !m_localUri.empty();
   }
 
   const std::string&
@@ -148,14 +152,14 @@
   bool
   hasFaceScope() const
   {
-    return m_hasFaceScope;
+    return !!m_faceScope;
   }
 
   FaceScope
   getFaceScope() const
   {
     BOOST_ASSERT(this->hasFaceScope());
-    return m_faceScope;
+    return *m_faceScope;
   }
 
   FaceQueryFilter&
@@ -167,14 +171,14 @@
   bool
   hasFacePersistency() const
   {
-    return m_hasFacePersistency;
+    return !!m_facePersistency;
   }
 
   FacePersistency
   getFacePersistency() const
   {
     BOOST_ASSERT(this->hasFacePersistency());
-    return m_facePersistency;
+    return *m_facePersistency;
   }
 
   FaceQueryFilter&
@@ -186,14 +190,14 @@
   bool
   hasLinkType() const
   {
-    return m_hasLinkType;
+    return !!m_linkType;
   }
 
   LinkType
   getLinkType() const
   {
     BOOST_ASSERT(this->hasLinkType());
-    return m_linkType;
+    return *m_linkType;
   }
 
   FaceQueryFilter&
@@ -203,21 +207,13 @@
   unsetLinkType();
 
 private:
-  uint64_t m_faceId;
+  optional<uint64_t> m_faceId;
   std::string m_uriScheme;
   std::string m_remoteUri;
   std::string m_localUri;
-  FaceScope m_faceScope;
-  FacePersistency m_facePersistency;
-  LinkType m_linkType;
-
-  bool m_hasFaceId;
-  bool m_hasUriScheme;
-  bool m_hasRemoteUri;
-  bool m_hasLocalUri;
-  bool m_hasFaceScope;
-  bool m_hasFacePersistency;
-  bool m_hasLinkType;
+  optional<FaceScope> m_faceScope;
+  optional<FacePersistency> m_facePersistency;
+  optional<LinkType> m_linkType;
 
   mutable Block m_wire;
 };
diff --git a/tests/unit-tests/mgmt/nfd/face-query-filter.t.cpp b/tests/unit-tests/mgmt/nfd/face-query-filter.t.cpp
index 7e91b8d..d8dbc67 100644
--- a/tests/unit-tests/mgmt/nfd/face-query-filter.t.cpp
+++ b/tests/unit-tests/mgmt/nfd/face-query-filter.t.cpp
@@ -84,6 +84,7 @@
 BOOST_AUTO_TEST_CASE(Equality)
 {
   FaceQueryFilter filter1, filter2;
+  BOOST_CHECK_EQUAL(filter1.empty(), true);
   BOOST_CHECK_EQUAL(filter1, filter2);
 
   filter1.setFaceId(100)
@@ -93,6 +94,7 @@
          .setFaceScope(FACE_SCOPE_LOCAL)
          .setFacePersistency(FACE_PERSISTENCY_ON_DEMAND)
          .setLinkType(LINK_TYPE_MULTI_ACCESS);
+  BOOST_CHECK_EQUAL(filter1.empty(), false);
   BOOST_CHECK_NE(filter1, filter2);
 
   filter2 = filter1;