security: Add transformation sink/source

Change-Id: I2698f79f639c2bd7c3ce2e00f48be634dc4c983d
Refs: #3009
diff --git a/src/security/transform/transform-base.hpp b/src/security/transform/transform-base.hpp
new file mode 100644
index 0000000..7f64145
--- /dev/null
+++ b/src/security/transform/transform-base.hpp
@@ -0,0 +1,249 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
+
+#include "../../common.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @file transform-base.hpp
+ *
+ * There are three types of module in a transformation chain: Source, Transform, and Sink.
+ * The ideal usage of the transformation would be:
+ *
+ *   source(...) >> transform1(...) >> transform2(...) >> sink(...);
+ *
+ * When error happens in a module, the module will throw out a transform::Error, one
+ * can get the location of the module through the getIndex() method of transform::Error.
+ */
+
+/**
+ * @brief Base class of transformation error
+ */
+class Error : public std::runtime_error
+{
+public:
+  Error(size_t index, const std::string& what);
+
+  size_t
+  getIndex() const
+  {
+    return m_index;
+  }
+
+private:
+  size_t m_index;
+};
+
+/**
+ * @brief The downstream interface of a transformation module
+ *
+ * A module can accept input through this interface
+ */
+class Downstream
+{
+public:
+  /**
+   * @brief Accept input data and perform transformation.
+   *
+   * An upstream module should call this method to write data into this module.
+   * The written data will be transformed and the result will be written into the next
+   * downstream module.
+   *
+   * An upstream module can keep calling this method to until end() is called, which
+   * indicates the end of input.  After that, calling this method will cause Error.
+   *
+   * If a Downstream implementation expects structured input (e.g., hex decoding requires byte-pair),
+   * it should not return less than size if final portion of input is not a complete record.
+   *
+   * @return number of bytes that has been written into this module
+   * @throws Error if this module is closed or transformation error happens.
+   */
+  size_t
+  write(const uint8_t* buf, size_t size);
+
+  /**
+   * @brief Close the input interface of a module.
+   *
+   * This method will notify this module that there is no more input and that the module
+   * should finalize transformation.
+   *
+   * Although end() can be invoked multiple times, only the first invocation takes effect.
+   */
+  void
+  end();
+
+  /**
+   * @brief Check if the input interface of a module is closed.
+   */
+  bool
+  isEnd() const
+  {
+    return m_isEnd;
+  }
+
+  /**
+   * @brief Set the module index.
+   */
+  void
+  setIndex(size_t index)
+  {
+    m_index = index;
+  }
+
+  /**
+   * @brief Get the module index.
+   */
+  size_t
+  getIndex() const
+  {
+    return m_index;
+  }
+
+protected:
+  Downstream();
+
+private:
+  /**
+   * @brief Internal implementation of write method
+   */
+  virtual size_t
+  doWrite(const uint8_t* buf, size_t size) = 0;
+
+  /**
+   * @brief Internal implementation of end method
+   */
+  virtual void
+  doEnd() = 0;
+
+private:
+  bool m_isEnd;
+  size_t m_index;
+};
+
+/**
+ * @brief The upstream interface of a transformation module
+ *
+ * A module can construct subsequent transformation chain through this interface.
+ */
+class Upstream
+{
+protected:
+  Upstream();
+
+protected:
+  /**
+   * @brief connect to next transformation module
+   */
+  void
+  appendChain(unique_ptr<Downstream> tail);
+
+  Downstream*
+  getNext()
+  {
+    return m_next.get();
+  }
+
+protected:
+  unique_ptr<Downstream> m_next;
+};
+
+/**
+ * @brief Abstraction of an intermediate transformation module
+ */
+class Transform : public Upstream,
+                  public Downstream,
+                  noncopyable
+{
+};
+
+/**
+ * @brief Abstraction of the transformation sink module
+ *
+ * This module does not have next module and can only accept input data
+ */
+class Sink : public Downstream,
+             noncopyable
+{
+};
+
+/**
+ * @brief Abstraction of the transformation source module
+ *
+ * This module can only accept input data from constructor
+ */
+class Source : public Upstream,
+               noncopyable
+{
+public:
+  /**
+   * @brief Connect to an intermediate transformation module.
+   */
+  Source&
+  operator>>(unique_ptr<Transform> transform);
+
+  /**
+   * @brief Connect to the last transformation module.
+   *
+   * This method will trigger the source to pump data into the transformation pipeline.
+   */
+  void
+  operator>>(unique_ptr<Sink> sink);
+
+protected:
+  Source();
+
+  /**
+   * @brief Pump all data into next transformation module.
+   */
+  void
+  pump();
+
+  /**
+   * @brief Get the source module index (should always be 0).
+   */
+  size_t
+  getIndex() const
+  {
+    return 0;
+  }
+
+private:
+  /**
+   * @brief Internal implementation of pump().
+   */
+  virtual void
+  doPump() = 0;
+
+private:
+  size_t m_nModules; // count of modules in the chain starting from this Source
+};
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_BASE_HPP