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