dissect: improve dissect program

This commit improves ndn-dissect program as follows:

* Functions are organized into NdnDissect class.
* The class is placed into namespace ndn::dissect.
* The main function is moved to main.cpp.
* Indentation is provided by ndn::util::IndentedStream.
* Command line parsing uses Boost.Program_options.
* -h and -V command line options are supported.

refs #2848

Change-Id: Ib12584f455910128662ed3f59631d13db52a2cf8
diff --git a/tools/dissect/main.cpp b/tools/dissect/main.cpp
new file mode 100644
index 0000000..fa1a962
--- /dev/null
+++ b/tools/dissect/main.cpp
@@ -0,0 +1,114 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  Regents of the University of California.
+ *
+ * This file is part of ndn-tools (Named Data Networking Essential Tools).
+ * See AUTHORS.md for complete list of ndn-tools authors and contributors.
+ *
+ * ndn-tools is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ndn-dissect.hpp"
+#include "core/version.hpp"
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+namespace po = boost::program_options;
+
+namespace ndn {
+namespace dissect {
+
+void
+usage(std::ostream& os, const std::string& appName, const po::options_description& options)
+{
+  os << "Usage:\n"
+     << "  " << appName << " [input-file] \n"
+     << "\n"
+     << options;
+}
+
+int
+main(int argc, char* argv[])
+{
+  po::options_description visibleOptions;
+  visibleOptions.add_options()
+    ("help,h", "Print help and exit.")
+    ("version,V", "Print version and exit.")
+    ;
+
+  std::string inputFileName;
+  po::options_description hiddenOptions;
+  hiddenOptions.add_options()
+    ("input-file", po::value<std::string>(&inputFileName));
+  ;
+  po::positional_options_description positionalArguments;
+  positionalArguments
+    .add("input-file", -1);
+
+  po::options_description allOptions;
+  allOptions
+    .add(visibleOptions)
+    .add(hiddenOptions)
+    ;
+
+  po::variables_map vm;
+  try {
+    po::store(po::command_line_parser(argc, argv)
+                .options(allOptions)
+                .positional(positionalArguments)
+                .run(),
+              vm);
+    po::notify(vm);
+  }
+  catch (po::error& e) {
+    std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
+    usage(std::cerr, argv[0], visibleOptions);
+    return 2;
+  }
+
+  if (vm.count("help") > 0) {
+    usage(std::cout, argv[0], visibleOptions);
+    return 0;
+  }
+
+  if (vm.count("version") > 0) {
+    std::cout << "ndn-dissect " << tools::VERSION << std::endl;
+    return 0;
+  }
+
+  std::ifstream inputFile;
+  std::istream* inputStream;
+
+  if (vm.count("input-file") > 0 && inputFileName != "-") {
+    inputFile.open(inputFileName);
+    inputStream = &inputFile;
+  }
+  else {
+    inputStream = &std::cin;
+  }
+
+  NdnDissect program;
+  program.dissect(std::cout, *inputStream);
+
+  return 0;
+}
+
+} // namespace dissect
+} // namespace ndn
+
+int
+main(int argc, char** argv)
+{
+  return ndn::dissect::main(argc, argv);
+}