tools: include CS config in 'nfdc cs info'

Also, ForwarderGeneralModule::formatItemText now uses ItemAttributes.

refs #4050

Change-Id: I1b2bde29b82e4b3910d87b41efd90e273052b18d
diff --git a/tools/nfd-status-http-server-files/nfd-status.xsl b/tools/nfd-status-http-server-files/nfd-status.xsl
index ada37d0..725e53e 100644
--- a/tools/nfd-status-http-server-files/nfd-status.xsl
+++ b/tools/nfd-status-http-server-files/nfd-status.xsl
@@ -327,12 +327,28 @@
   <table class="item-list">
     <thead>
       <tr>
+        <th>Enablement Flags</th>
+        <th>Capacity</th>
+        <th>Entries</th>
         <th>Hits</th>
         <th>Misses</th>
       </tr>
     </thead>
     <tbody>
       <tr>
+        <td>
+          <xsl:choose>
+            <xsl:when test="nfd:admitEnabled">admit</xsl:when>
+            <xsl:otherwise>no-admit</xsl:otherwise>
+          </xsl:choose>
+          ,
+          <xsl:choose>
+            <xsl:when test="nfd:serveEnabled">serve</xsl:when>
+            <xsl:otherwise>no-serve</xsl:otherwise>
+          </xsl:choose>
+        </td>
+        <td><xsl:value-of select="nfd:capacity"/></td>
+        <td><xsl:value-of select="nfd:nEntries"/></td>
         <td><xsl:value-of select="nfd:nHits"/></td>
         <td><xsl:value-of select="nfd:nMisses"/></td>
       </tr>
diff --git a/tools/nfdc/cs-module.cpp b/tools/nfdc/cs-module.cpp
index 9d28855..d42b82e 100644
--- a/tools/nfdc/cs-module.cpp
+++ b/tools/nfdc/cs-module.cpp
@@ -26,6 +26,8 @@
 #include "cs-module.hpp"
 #include "format-helpers.hpp"
 
+#include <ndn-cxx/util/indented-stream.hpp>
+
 namespace nfd {
 namespace tools {
 namespace nfdc {
@@ -94,21 +96,41 @@
 void
 CsModule::formatStatusXml(std::ostream& os) const
 {
+  formatItemXml(os, m_status);
+}
+
+void
+CsModule::formatItemXml(std::ostream& os, const CsInfo& item)
+{
   os << "<cs>";
-  os << "<nHits>" << m_status.getNHits() << "</nHits>";
-  os << "<nMisses>" << m_status.getNMisses() << "</nMisses>";
+  os << "<capacity>" << item.getCapacity() << "</capacity>";
+  os << xml::Flag{"admitEnabled", item.getEnableAdmit()};
+  os << xml::Flag{"serveEnabled", item.getEnableServe()};
+  os << "<nEntries>" << item.getNEntries() << "</nEntries>";
+  os << "<nHits>" << item.getNHits() << "</nHits>";
+  os << "<nMisses>" << item.getNMisses() << "</nMisses>";
   os << "</cs>";
 }
 
 void
 CsModule::formatStatusText(std::ostream& os) const
 {
-  os << "CS information:\n  ";
-  text::ItemAttributes ia;
-  os << ia("nHits") << m_status.getNHits()
-     << ia("nMisses") << m_status.getNMisses()
+  os << "CS information:\n";
+  ndn::util::IndentedStream indented(os, "  ");
+  formatItemText(indented, m_status);
+}
+
+void
+CsModule::formatItemText(std::ostream& os, const CsInfo& item)
+{
+  text::ItemAttributes ia(true, 8);
+  os << ia("capacity") << item.getCapacity()
+     << ia("admit") << text::OnOff{item.getEnableAdmit()}
+     << ia("serve") << text::OnOff{item.getEnableServe()}
+     << ia("nEntries") << item.getNEntries()
+     << ia("nHits") << item.getNHits()
+     << ia("nMisses") << item.getNMisses()
      << ia.end();
-  os << '\n';
 }
 
 } // namespace nfdc
diff --git a/tools/nfdc/cs-module.hpp b/tools/nfdc/cs-module.hpp
index 7634d3d..320ce09 100644
--- a/tools/nfdc/cs-module.hpp
+++ b/tools/nfdc/cs-module.hpp
@@ -60,9 +60,15 @@
   void
   formatStatusXml(std::ostream& os) const override;
 
+  static void
+  formatItemXml(std::ostream& os, const CsInfo& item);
+
   void
   formatStatusText(std::ostream& os) const override;
 
+  static void
+  formatItemText(std::ostream& os, const CsInfo& item);
+
 private:
   CsInfo m_status;
 };
diff --git a/tools/nfdc/face-module.cpp b/tools/nfdc/face-module.cpp
index 85673a8..888a7b3 100644
--- a/tools/nfdc/face-module.cpp
+++ b/tools/nfdc/face-module.cpp
@@ -405,15 +405,9 @@
   }
   else {
     os << "<flags>";
-    if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
-      os << "<localFieldsEnabled/>";
-    }
-    if (item.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
-      os << "<lpReliabilityEnabled/>";
-    }
-    if (item.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
-      os << "<congestionMarkingEnabled/>";
-    }
+    os << xml::Flag{"localFieldsEnabled", item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)};
+    os << xml::Flag{"lpReliabilityEnabled", item.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)};
+    os << xml::Flag{"congestionMarkingEnabled", item.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)};
     os << "</flags>";
   }
 
diff --git a/tools/nfdc/format-helpers.cpp b/tools/nfdc/format-helpers.cpp
index a329102..d898dc3 100644
--- a/tools/nfdc/format-helpers.cpp
+++ b/tools/nfdc/format-helpers.cpp
@@ -75,6 +75,15 @@
   return os;
 }
 
+std::ostream&
+operator<<(std::ostream& os, Flag v)
+{
+  if (!v.flag) {
+    return os;
+  }
+  return os << '<' << v.elementName << "/>";
+}
+
 std::string
 formatDuration(time::nanoseconds d)
 {
diff --git a/tools/nfdc/format-helpers.hpp b/tools/nfdc/format-helpers.hpp
index 0d131f1..957773b 100644
--- a/tools/nfdc/format-helpers.hpp
+++ b/tools/nfdc/format-helpers.hpp
@@ -50,6 +50,17 @@
 std::ostream&
 operator<<(std::ostream& os, const Text& text);
 
+/** \brief print true as an empty element and false as nothing
+ */
+struct Flag
+{
+  const char* elementName;
+  bool flag;
+};
+
+std::ostream&
+operator<<(std::ostream& os, Flag v);
+
 /** \return duration in XML duration format
  *
  *  Definition of this format: https://www.w3.org/TR/xmlschema11-2/#duration
diff --git a/tools/nfdc/forwarder-general-module.cpp b/tools/nfdc/forwarder-general-module.cpp
index 4a85cdd..67093ec 100644
--- a/tools/nfdc/forwarder-general-module.cpp
+++ b/tools/nfdc/forwarder-general-module.cpp
@@ -26,6 +26,8 @@
 #include "forwarder-general-module.hpp"
 #include "format-helpers.hpp"
 
+#include <ndn-cxx/util/indented-stream.hpp>
+
 namespace nfd {
 namespace tools {
 namespace nfdc {
@@ -53,11 +55,11 @@
 void
 ForwarderGeneralModule::formatStatusXml(std::ostream& os) const
 {
-  this->formatItemXml(os, m_status);
+  formatItemXml(os, m_status);
 }
 
 void
-ForwarderGeneralModule::formatItemXml(std::ostream& os, const ForwarderStatus& item) const
+ForwarderGeneralModule::formatItemXml(std::ostream& os, const ForwarderStatus& item)
 {
   os << "<generalStatus>";
 
@@ -93,29 +95,34 @@
 ForwarderGeneralModule::formatStatusText(std::ostream& os) const
 {
   os << "General NFD status:\n";
-  this->formatItemText(os, m_status);
+  ndn::util::IndentedStream indented(os, "  ");
+  formatItemText(indented, m_status);
 }
 
 void
-ForwarderGeneralModule::formatItemText(std::ostream& os, const ForwarderStatus& item) const
+ForwarderGeneralModule::formatItemText(std::ostream& os, const ForwarderStatus& item)
 {
-  os << "               version=" << item.getNfdVersion() << "\n";
-  os << "             startTime=" << text::formatTimestamp(item.getStartTimestamp()) << "\n";
-  os << "           currentTime=" << text::formatTimestamp(item.getCurrentTimestamp()) << "\n";
-  os << "                uptime=" << text::formatDuration<time::seconds>(calculateUptime(item), true) << "\n";
+  text::ItemAttributes ia(true, 20);
 
-  os << "      nNameTreeEntries=" << item.getNNameTreeEntries() << "\n";
-  os << "           nFibEntries=" << item.getNFibEntries() << "\n";
-  os << "           nPitEntries=" << item.getNPitEntries() << "\n";
-  os << "  nMeasurementsEntries=" << item.getNMeasurementsEntries() << "\n";
-  os << "            nCsEntries=" << item.getNCsEntries() << "\n";
+  os << ia("version") << item.getNfdVersion()
+     << ia("startTime") << text::formatTimestamp(item.getStartTimestamp())
+     << ia("currentTime") << text::formatTimestamp(item.getCurrentTimestamp())
+     << ia("uptime") << text::formatDuration<time::seconds>(calculateUptime(item), true);
 
-  os << "          nInInterests=" << item.getNInInterests() << "\n";
-  os << "         nOutInterests=" << item.getNOutInterests() << "\n";
-  os << "               nInData=" << item.getNInData() << "\n";
-  os << "              nOutData=" << item.getNOutData() << "\n";
-  os << "              nInNacks=" << item.getNInNacks() << "\n";
-  os << "             nOutNacks=" << item.getNOutNacks() << "\n";
+  os << ia("nNameTreeEntries") << item.getNNameTreeEntries()
+     << ia("nFibEntries") << item.getNFibEntries()
+     << ia("nPitEntries") << item.getNPitEntries()
+     << ia("nMeasurementsEntries") << item.getNMeasurementsEntries()
+     << ia("nCsEntries") << item.getNCsEntries();
+
+  os << ia("nInInterests") << item.getNInInterests()
+     << ia("nOutInterests") << item.getNOutInterests()
+     << ia("nInData") << item.getNInData()
+     << ia("nOutData") << item.getNOutData()
+     << ia("nInNacks") << item.getNInNacks()
+     << ia("nOutNacks") << item.getNOutNacks();
+
+  os << ia.end();
 }
 
 } // namespace nfdc
diff --git a/tools/nfdc/forwarder-general-module.hpp b/tools/nfdc/forwarder-general-module.hpp
index 4d65c83..4619cfa 100644
--- a/tools/nfdc/forwarder-general-module.hpp
+++ b/tools/nfdc/forwarder-general-module.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -53,8 +53,8 @@
    *  \param os output stream
    *  \param item status item
    */
-  void
-  formatItemXml(std::ostream& os, const ForwarderStatus& item) const;
+  static void
+  formatItemXml(std::ostream& os, const ForwarderStatus& item);
 
   void
   formatStatusText(std::ostream& os) const override;
@@ -63,8 +63,8 @@
    *  \param os output stream
    *  \param item status item
    */
-  void
-  formatItemText(std::ostream& os, const ForwarderStatus& item) const;
+  static void
+  formatItemText(std::ostream& os, const ForwarderStatus& item);
 
 private:
   ForwarderStatus m_status;