tools: implement 'nfdc cs erase' command

refs #4318

Change-Id: If4dc401a3efff44a5bf4b3074d21797f8384cf9f
diff --git a/tools/nfdc/cs-module.cpp b/tools/nfdc/cs-module.cpp
index 6a3b0b5..fafd095 100644
--- a/tools/nfdc/cs-module.cpp
+++ b/tools/nfdc/cs-module.cpp
@@ -42,6 +42,13 @@
     .addArg("admit", ArgValueType::BOOLEAN, Required::NO, Positional::NO)
     .addArg("serve", ArgValueType::BOOLEAN, Required::NO, Positional::NO);
   parser.addCommand(defCsConfig, &CsModule::config);
+
+  CommandDefinition defCsErase("cs", "erase");
+  defCsErase
+    .setTitle("erase cached Data")
+    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
+    .addArg("count", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
+  parser.addCommand(defCsErase, &CsModule::erase);
 }
 
 void
@@ -80,6 +87,34 @@
 }
 
 void
+CsModule::erase(ExecuteContext& ctx)
+{
+  auto prefix = ctx.args.get<Name>("prefix");
+  auto count = ctx.args.getOptional<uint64_t>("count");
+
+  ControlParameters params;
+  params.setName(prefix);
+  if (count) {
+    params.setCount(*count);
+  }
+
+  ctx.controller.start<ndn::nfd::CsEraseCommand>(
+    params,
+    [&] (const ControlParameters& resp) {
+      text::ItemAttributes ia;
+      ctx.out << "cs-erased "
+              << ia("prefix") << resp.getName()
+              << ia("count") << resp.getCount()
+              << ia("has-more") << text::YesNo{resp.hasCapacity()}
+              << '\n';
+    },
+    ctx.makeCommandFailureHandler("erasing cached Data"),
+    ctx.makeCommandOptions());
+
+  ctx.face.processEvents();
+}
+
+void
 CsModule::fetchStatus(Controller& controller,
                       const std::function<void()>& onSuccess,
                       const Controller::DatasetFailCallback& onFailure,
diff --git a/tools/nfdc/cs-module.hpp b/tools/nfdc/cs-module.hpp
index 4181290..3b16952 100644
--- a/tools/nfdc/cs-module.hpp
+++ b/tools/nfdc/cs-module.hpp
@@ -51,6 +51,11 @@
   static void
   config(ExecuteContext& ctx);
 
+  /** \brief the 'cs erase' command
+   */
+  static void
+  erase(ExecuteContext& ctx);
+
   void
   fetchStatus(Controller& controller,
               const std::function<void()>& onSuccess,
diff --git a/tools/nfdc/format-helpers.cpp b/tools/nfdc/format-helpers.cpp
index d898dc3..fa72512 100644
--- a/tools/nfdc/format-helpers.cpp
+++ b/tools/nfdc/format-helpers.cpp
@@ -192,6 +192,12 @@
   return os << (v.flag ? "on" : "off");
 }
 
+std::ostream&
+operator<<(std::ostream& os, YesNo v)
+{
+  return os << (v.flag ? "yes" : "no");
+}
+
 std::string
 formatTimestamp(time::system_clock::TimePoint t)
 {
diff --git a/tools/nfdc/format-helpers.hpp b/tools/nfdc/format-helpers.hpp
index 957773b..1ee88ee 100644
--- a/tools/nfdc/format-helpers.hpp
+++ b/tools/nfdc/format-helpers.hpp
@@ -186,6 +186,16 @@
 std::ostream&
 operator<<(std::ostream& os, OnOff v);
 
+/** \brief print boolean as 'yes' or 'no'
+ */
+struct YesNo
+{
+  bool flag;
+};
+
+std::ostream&
+operator<<(std::ostream& os, YesNo v);
+
 namespace detail {
 
 template<typename DurationT>