tools: various improvements in nfdc

* use same underlying type for ParseMode and AvailableIn,
  to avoid potential errors when converting between them
* simplify AvailableIn stream output operator with text::Separator
* allow CommandParser::addCommand to accept bitwise OR'ed modes
* qualify nfdc logging sources with 'nfdc.' prefix

refs #3780

Change-Id: I2eee3d562184daf27305c2d5f2892637b63421c2
diff --git a/tools/nfdc/command-definition.cpp b/tools/nfdc/command-definition.cpp
index cb25c7c..67ca456 100644
--- a/tools/nfdc/command-definition.cpp
+++ b/tools/nfdc/command-definition.cpp
@@ -33,7 +33,7 @@
 namespace tools {
 namespace nfdc {
 
-NDN_LOG_INIT(CommandDefinition);
+NDN_LOG_INIT(nfdc.CommandDefinition);
 
 std::ostream&
 operator<<(std::ostream& os, ArgValueType vt)
diff --git a/tools/nfdc/command-parser.cpp b/tools/nfdc/command-parser.cpp
index 974c931..6b21d8b 100644
--- a/tools/nfdc/command-parser.cpp
+++ b/tools/nfdc/command-parser.cpp
@@ -24,33 +24,31 @@
  */
 
 #include "command-parser.hpp"
+#include "format-helpers.hpp"
 #include <ndn-cxx/util/logger.hpp>
 
 namespace nfd {
 namespace tools {
 namespace nfdc {
 
-NDN_LOG_INIT(CommandParser);
+NDN_LOG_INIT(nfdc.CommandParser);
+
+static_assert(std::is_same<std::underlying_type<AvailableIn>::type,
+                           std::underlying_type<ParseMode>::type>::value,
+              "AvailableIn and ParseMode must be declared with same underlying type");
 
 std::ostream&
 operator<<(std::ostream& os, AvailableIn modes)
 {
-  int count = 0;
-
-#define PRINT_BIT(bit, str) \
-  if ((modes & bit) != 0) { \
-    if (++count > 1) { \
-      os << '|'; \
-    } \
-    os << str; \
+  text::Separator sep("|");
+  if ((modes & AVAILABLE_IN_ONE_SHOT) != 0) {
+    os << sep << "one-shot";
+  }
+  if ((modes & AVAILABLE_IN_BATCH) != 0) {
+    os << sep << "batch";
   }
 
-  PRINT_BIT(AVAILABLE_IN_ONE_SHOT, "one-shot")
-  PRINT_BIT(AVAILABLE_IN_BATCH, "batch")
-
-#undef PRINT_BIT
-
-  if (count == 0) {
+  if (sep.getCount() == 0) {
     os << "none";
   }
   return os;
@@ -69,10 +67,12 @@
 }
 
 CommandParser&
-CommandParser::addCommand(const CommandDefinition& def, const ExecuteCommand& execute, AvailableIn modes)
+CommandParser::addCommand(const CommandDefinition& def, const ExecuteCommand& execute,
+                          std::underlying_type<AvailableIn>::type modes)
 {
   BOOST_ASSERT(modes != AVAILABLE_IN_NONE);
-  m_commands[{def.getNoun(), def.getVerb()}].reset(new Command{def, execute, modes});
+  m_commands[{def.getNoun(), def.getVerb()}].reset(
+    new Command{def, execute, static_cast<AvailableIn>(modes)});
   return *this;
 }
 
diff --git a/tools/nfdc/command-parser.hpp b/tools/nfdc/command-parser.hpp
index 3a853c5..a46530d 100644
--- a/tools/nfdc/command-parser.hpp
+++ b/tools/nfdc/command-parser.hpp
@@ -28,6 +28,7 @@
 
 #include "command-definition.hpp"
 #include "execute-command.hpp"
+#include <type_traits>
 
 namespace nfd {
 namespace tools {
@@ -37,8 +38,8 @@
  */
 enum AvailableIn : uint8_t {
   AVAILABLE_IN_NONE     = 0,
-  AVAILABLE_IN_ONE_SHOT = 1 << 0,
-  AVAILABLE_IN_BATCH    = 1 << 1,
+  AVAILABLE_IN_ONE_SHOT = 1 << 0, ///< one-shot mode
+  AVAILABLE_IN_BATCH    = 1 << 1, ///< batch mode
   AVAILABLE_IN_ALL      = 0xff
 };
 
@@ -47,7 +48,7 @@
 
 /** \brief indicates which mode is the parser operated in
  */
-enum class ParseMode {
+enum class ParseMode : uint8_t {
   ONE_SHOT = AVAILABLE_IN_ONE_SHOT, ///< one-shot mode
   BATCH    = AVAILABLE_IN_BATCH     ///< batch mode
 };
@@ -76,7 +77,8 @@
    *  \param modes parse modes this command should be available in, must not be AVAILABLE_IN_NONE
    */
   CommandParser&
-  addCommand(const CommandDefinition& def, const ExecuteCommand& execute, AvailableIn modes = AVAILABLE_IN_ALL);
+  addCommand(const CommandDefinition& def, const ExecuteCommand& execute,
+             std::underlying_type<AvailableIn>::type modes = AVAILABLE_IN_ALL);
 
   /** \brief add an alias "noun verb2" to existing command "noun verb"
    *  \throw std::out_of_range "noun verb" does not exist
@@ -104,7 +106,10 @@
     AvailableIn modes;
   };
 
-  std::map<CommandName, shared_ptr<Command>> m_commands;
+  /** \brief map from command name or alias to command definition
+   */
+  typedef std::map<CommandName, shared_ptr<Command>> CommandContainer;
+  CommandContainer m_commands;
 };
 
 } // namespace nfdc
diff --git a/tools/nfdc/format-helpers.hpp b/tools/nfdc/format-helpers.hpp
index 84efe7b..6629409 100644
--- a/tools/nfdc/format-helpers.hpp
+++ b/tools/nfdc/format-helpers.hpp
@@ -85,6 +85,12 @@
   explicit
   Separator(const std::string& subsequent);
 
+  int
+  getCount() const
+  {
+    return m_count;
+  }
+
 private:
   std::string m_first;
   std::string m_subsequent;