tools: Allow verbose option in ndnsec-list/ndnsec-ls-identity command line tools

Change-Id: I019ae8b8ee049529fbdc3c2ed42ffebddf664d78
Refs: #2197
diff --git a/tools/ndnsec-util.hpp b/tools/ndnsec-util.hpp
index 1503065..14ddf48 100644
--- a/tools/ndnsec-util.hpp
+++ b/tools/ndnsec-util.hpp
@@ -90,4 +90,136 @@
     return ndn::io::load<ndn::IdentityCertificate>(fileName);
 }
 
-#endif //NDNSEC_UTIL_HPP
+
+/**
+ * @brief An accumulating option value to handle multiple incrementing options.
+ *
+ * Based on https://gitorious.org/bwy/bwy/source/8753148c324ddfacb1f3cdc315650586bd7b75a4:use/accumulator.hpp
+ * @sa http://benjaminwolsey.de/node/103
+ */
+template<typename T>
+class AccumulatorType : public boost::program_options::value_semantic
+{
+public:
+  explicit
+  AccumulatorType(T* store)
+    : m_store(store)
+    , m_interval(1)
+    , m_default(0)
+  {
+  }
+
+  virtual
+  ~AccumulatorType()
+  {
+  }
+
+  /// @brief Set the default value for this option.
+  AccumulatorType*
+  setDefaultValue(const T& t)
+  {
+    m_default = t;
+    return this;
+  }
+
+  /**
+   * @brief Set the interval for this option.
+   *
+   * Unlike for program_options::value, this specifies a value
+   * to be applied on each occurrence of the option.
+   */
+  AccumulatorType*
+  setInterval(const T& t) {
+    m_interval = t;
+    return this;
+  }
+
+  virtual std::string
+  name() const
+  {
+    return std::string();
+  }
+
+  // There are no tokens for an AccumulatorType
+  virtual unsigned
+  min_tokens() const
+  {
+    return 0;
+  }
+
+  virtual unsigned
+  max_tokens() const
+  {
+    return 0;
+  }
+
+  // Accumulating from different sources is silly.
+  virtual bool
+  is_composing() const
+  {
+    return false;
+  }
+
+  // Requiring one or more appearances is unlikely.
+  virtual bool
+  is_required() const
+  {
+    return false;
+  }
+
+  /**
+   * @brief Parse options
+   *
+   * Every appearance of the option simply increments the value
+   * There should never be any tokens.
+   */
+  virtual void
+  parse(boost::any& value_store,
+        const std::vector<std::string>& new_tokens,
+        bool utf8) const
+  {
+    if (value_store.empty())
+      value_store = T();
+    boost::any_cast<T&>(value_store) += m_interval;
+  }
+
+  /**
+   * @brief If the option doesn't appear, this is the default value.
+   */
+  virtual bool
+  apply_default(boost::any& value_store) const
+  {
+    value_store = m_default;
+    return true;
+  }
+
+  /**
+   * @brief Notify the user function with the value of the value store.
+   */
+  virtual void
+  notify(const boost::any& value_store) const
+  {
+    const T* val = boost::any_cast<T>(&value_store);
+    if (m_store)
+      *m_store = *val;
+  }
+
+private:
+    T* m_store;
+    T m_interval;
+    T m_default;
+};
+
+template<typename T>
+AccumulatorType<T>* accumulator()
+{
+  return new AccumulatorType<T>(0);
+}
+
+template<typename T>
+AccumulatorType<T>* accumulator(T* store)
+{
+  return new AccumulatorType<T>(store);
+}
+
+#endif // NDNSEC_UTIL_HPP