security: Add transformation sink/source
Change-Id: I2698f79f639c2bd7c3ce2e00f48be634dc4c983d
Refs: #3009
diff --git a/src/security/transform.hpp b/src/security/transform.hpp
new file mode 100644
index 0000000..b29f5c6
--- /dev/null
+++ b/src/security/transform.hpp
@@ -0,0 +1,32 @@
+/* -*- 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_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_HPP
+
+#include "transform/buffer-source.hpp"
+#include "transform/stream-source.hpp"
+#include "transform/step-source.hpp"
+
+#include "transform/bool-sink.hpp"
+#include "transform/stream-sink.hpp"
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_HPP
diff --git a/src/security/transform/bool-sink.cpp b/src/security/transform/bool-sink.cpp
new file mode 100644
index 0000000..1c45c76
--- /dev/null
+++ b/src/security/transform/bool-sink.cpp
@@ -0,0 +1,58 @@
+/* -*- 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.
+ */
+
+#include "bool-sink.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+BoolSink::BoolSink(bool& value)
+ : m_hasValue(false)
+ , m_value(value)
+{
+}
+
+size_t
+BoolSink::doWrite(const uint8_t* buf, size_t size)
+{
+ if (!m_hasValue && size > 0) {
+ m_value = (buf[0] != 0);
+ m_hasValue = true;
+ }
+ return size;
+}
+
+void
+BoolSink::doEnd()
+{
+ // nothing to do.
+}
+
+unique_ptr<Sink>
+boolSink(bool& value)
+{
+ return make_unique<BoolSink>(value);
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/bool-sink.hpp b/src/security/transform/bool-sink.hpp
new file mode 100644
index 0000000..12e62c9
--- /dev/null
+++ b/src/security/transform/bool-sink.hpp
@@ -0,0 +1,73 @@
+/* -*- 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_BOOL_SINK_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_BOOL_SINK_HPP
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief A sink which outputs only one boolean value.
+ *
+ * It checks the first byte that is ever written into the sink,
+ * and set output true if the byte is non-zero, otherwise false.
+ */
+class BoolSink : public Sink
+{
+public:
+ /**
+ * @brief Create a bool sink whose output will be stored in @p value.
+ */
+ explicit
+ BoolSink(bool& value);
+
+private:
+ /**
+ * @brief Check the first byte that is ever received and set the boolean variable.
+ *
+ * @return the same value as @p size.
+ */
+ virtual size_t
+ doWrite(const uint8_t* buf, size_t size) final;
+
+ /**
+ * @brief Finalize sink processing
+ */
+ virtual void
+ doEnd() final;
+
+private:
+ bool m_hasValue;
+ bool& m_value;
+};
+
+unique_ptr<Sink>
+boolSink(bool& value);
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_BOOL_SINK_HPP
diff --git a/src/security/transform/buffer-source.cpp b/src/security/transform/buffer-source.cpp
new file mode 100644
index 0000000..b47e855
--- /dev/null
+++ b/src/security/transform/buffer-source.cpp
@@ -0,0 +1,65 @@
+/* -*- 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.
+ */
+
+#include "buffer-source.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+BufferSource::BufferSource(const uint8_t* buf, size_t size)
+ : m_buf(buf)
+ , m_size(size)
+{
+}
+
+BufferSource::BufferSource(const std::string& string)
+ : m_buf(reinterpret_cast<const uint8_t*>(string.data()))
+ , m_size(string.size())
+{
+}
+
+BufferSource::BufferSource(const Buffer& buffer)
+ : m_buf(buffer.buf())
+ , m_size(buffer.size())
+{
+}
+
+void
+BufferSource::doPump()
+{
+ BOOST_ASSERT(m_next != nullptr);
+
+ const uint8_t* buf = m_buf;
+ size_t size = m_size;
+
+ while (0 < size) {
+ size_t nBytesWritten = m_next->write(buf, size);
+ buf += nBytesWritten;
+ size -= nBytesWritten;
+ }
+
+ m_next->end();
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/buffer-source.hpp b/src/security/transform/buffer-source.hpp
new file mode 100644
index 0000000..0833a0f
--- /dev/null
+++ b/src/security/transform/buffer-source.hpp
@@ -0,0 +1,79 @@
+/* -*- 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_BUFFER_SOURCE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_BUFFER_SOURCE_HPP
+
+#include "transform-base.hpp"
+#include "../../encoding/buffer.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief A source taking a memory buffer as input
+ */
+class BufferSource : public Source
+{
+public:
+ /**
+ * @brief Take a buffer @p buf with size of @p size as input.
+ *
+ * Caller must not destroy the buffer before transformation is done
+ */
+ BufferSource(const uint8_t* buf, size_t size);
+
+ /**
+ * @brief Take @p string as input.
+ *
+ * Caller must not destroy the string before transformation is done
+ */
+ explicit
+ BufferSource(const std::string& string);
+
+ /**
+ * @brief Take @p buffer as input.
+ *
+ * Caller must not destroy the buffer before transformation is done
+ */
+ explicit
+ BufferSource(const Buffer& buffer);
+
+private:
+ /**
+ * @brief Write the whole buffer into the next module.
+ */
+ virtual void
+ doPump() final;
+
+private:
+ const uint8_t* m_buf;
+ size_t m_size;
+};
+
+typedef BufferSource bufferSource;
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_BUFFER_SOURCE_HPP
diff --git a/src/security/transform/step-source.cpp b/src/security/transform/step-source.cpp
new file mode 100644
index 0000000..432ebd9
--- /dev/null
+++ b/src/security/transform/step-source.cpp
@@ -0,0 +1,48 @@
+/* -*- 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.
+ */
+
+#include "step-source.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+size_t
+StepSource::write(const uint8_t* buf, size_t size)
+{
+ return m_next->write(buf, size);
+}
+
+void
+StepSource::end()
+{
+ m_next->end();
+}
+
+
+void
+StepSource::doPump()
+{
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/step-source.hpp b/src/security/transform/step-source.hpp
new file mode 100644
index 0000000..76388f7
--- /dev/null
+++ b/src/security/transform/step-source.hpp
@@ -0,0 +1,82 @@
+/* -*- 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_STEP_SOURCE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_STEP_SOURCE_HPP
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief A source that can accept input step by step, and can close input explicitly.
+ *
+ * This source will not send data into the transformation chain when the chain is constructed.
+ * Input will be explicitly sent into the chain using write(...) and will be closed explicitly
+ * using end().
+ *
+ * StepSource ss;
+ * ss >> transform1() >> transform2() >> sinkStream(...);
+ * ss.write(...);
+ * ...
+ * ss.write(...);
+ * ss.end();
+ */
+class StepSource : public Source
+{
+public:
+ /**
+ * @brief Accept input data and directly write input into next transformation module.
+ *
+ * One can keep calling this method to until end() is called, which
+ * indicates the end of input. After that, calling this method will cause Error.
+ *
+ * @return number of bytes that has been written into next module
+ */
+ size_t
+ write(const uint8_t* buf, size_t size);
+
+ /**
+ * @brief Close the input interface and directly notify the next module the end of input
+ */
+ void
+ end();
+
+private:
+ /**
+ * @brief This method intentionally does nothing
+ *
+ * use write() and end() method explicitly to input data.
+ */
+ virtual void
+ doPump() final;
+
+};
+
+typedef StepSource stepSource;
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_STEP_SOURCE_HPP
diff --git a/src/security/transform/stream-sink.cpp b/src/security/transform/stream-sink.cpp
new file mode 100644
index 0000000..58208c0
--- /dev/null
+++ b/src/security/transform/stream-sink.cpp
@@ -0,0 +1,59 @@
+/* -*- 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.
+ */
+
+#include "stream-sink.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+StreamSink::StreamSink(std::ostream& os)
+ : m_os(os)
+{
+}
+
+size_t
+StreamSink::doWrite(const uint8_t* buf, size_t size)
+{
+ m_os.write(reinterpret_cast<const char*>(buf), size);
+
+ if (m_os.bad())
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Fail to write data into output stream"));
+
+ return size;
+}
+
+void
+StreamSink::doEnd()
+{
+ m_os.flush();
+}
+
+unique_ptr<Sink>
+streamSink(std::ostream& os)
+{
+ return make_unique<StreamSink>(os);
+}
+
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/stream-sink.hpp b/src/security/transform/stream-sink.hpp
new file mode 100644
index 0000000..ed41cbd
--- /dev/null
+++ b/src/security/transform/stream-sink.hpp
@@ -0,0 +1,70 @@
+/* -*- 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_STREAM_SINK_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_STREAM_SINK_HPP
+
+#include "transform-base.hpp"
+#include <iostream>
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief A sink which directs output to an std::ostream.
+ */
+class StreamSink : public Sink
+{
+public:
+ /**
+ * @brief Create a stream sink which outputs to @p os
+ */
+ explicit
+ StreamSink(std::ostream& os);
+
+private:
+ /**
+ * @brief Write data into the stream
+ *
+ * @return number of bytes that have been written into the stream
+ */
+ virtual size_t
+ doWrite(const uint8_t* buf, size_t size) final;
+
+ /**
+ * @brief Finalize sink processing
+ */
+ virtual void
+ doEnd() final;
+
+private:
+ std::ostream& m_os;
+};
+
+unique_ptr<Sink>
+streamSink(std::ostream& os);
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_STREAM_SINK_HPP
diff --git a/src/security/transform/stream-source.cpp b/src/security/transform/stream-source.cpp
new file mode 100644
index 0000000..5248646
--- /dev/null
+++ b/src/security/transform/stream-source.cpp
@@ -0,0 +1,70 @@
+/* -*- 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.
+ */
+
+#include "stream-source.hpp"
+#include <vector>
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+const std::size_t StreamSource::DEFAULT_BUFFER_LEN = 1024;
+
+StreamSource::StreamSource(std::istream& is, size_t bufferSize)
+ : Source()
+ , m_is(is)
+ , m_bufferSize(bufferSize)
+{
+ BOOST_ASSERT(bufferSize > 0);
+}
+
+void
+StreamSource::doPump()
+{
+ BOOST_ASSERT(m_next != nullptr);
+
+ std::vector<uint8_t> buffer(m_bufferSize);
+ size_t dataOffset = 0;
+ size_t dataLen = 0;
+
+ while (dataLen > 0 || !m_is.eof()) {
+ if (dataLen > 0) {
+ // we have some leftover, handle them first
+ size_t nBytesWritten = m_next->write(&buffer[dataOffset], dataLen);
+
+ dataOffset += nBytesWritten;
+ dataLen -= nBytesWritten;
+ }
+ else if (m_is.bad()) {
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Input stream in bad state"));
+ }
+ else if (m_is.good()) {
+ m_is.read(reinterpret_cast<char*>(&buffer.front()), buffer.size());
+ dataOffset = 0;
+ dataLen = m_is.gcount();
+ }
+ }
+ m_next->end();
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/src/security/transform/stream-source.hpp b/src/security/transform/stream-source.hpp
new file mode 100644
index 0000000..b818fe7
--- /dev/null
+++ b/src/security/transform/stream-source.hpp
@@ -0,0 +1,69 @@
+/* -*- 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_STREAM_SOURCE_HPP
+#define NDN_CXX_SECURITY_TRANSFORM_STREAM_SOURCE_HPP
+
+#include "transform-base.hpp"
+#include <iostream>
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+/**
+ * @brief A source taking an std::istream as input
+ */
+class StreamSource : public Source
+{
+public:
+ /**
+ * @brief Construst a source using @p is as input.
+ *
+ * @param is The input stream
+ * @param bufLen The internal buffer size. The default size is 1024.
+ * @pre bufLen must be larger than 0.
+ */
+ explicit
+ StreamSource(std::istream& is, size_t bufLen = DEFAULT_BUFFER_LEN);
+
+private:
+ /**
+ * @brief Read bytes from the input stream until EOF is reached and write them into the next module.
+ */
+ virtual void
+ doPump() final;
+
+public:
+ static const std::size_t DEFAULT_BUFFER_LEN;
+
+private:
+ std::istream& m_is;
+ size_t m_bufferSize;
+};
+
+typedef StreamSource streamSource;
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_CXX_SECURITY_TRANSFORM_STREAM_SOURCE_HPP
diff --git a/src/security/transform/transform-base.cpp b/src/security/transform/transform-base.cpp
new file mode 100644
index 0000000..85df6b9
--- /dev/null
+++ b/src/security/transform/transform-base.cpp
@@ -0,0 +1,110 @@
+/* -*- 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.
+ */
+
+#include "transform-base.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+Error::Error(size_t index, const std::string& what)
+ : std::runtime_error("Error in module " + std::to_string(index) + ": " + what)
+ , m_index(index)
+{
+}
+
+Downstream::Downstream()
+ : m_isEnd(false)
+{
+}
+
+size_t
+Downstream::write(const uint8_t* buf, size_t size)
+{
+ if (m_isEnd)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Module is closed, no more input"));
+
+ size_t nBytesWritten = doWrite(buf, size);
+ BOOST_ASSERT(nBytesWritten <= size);
+ return nBytesWritten;
+}
+
+void
+Downstream::end()
+{
+ if (m_isEnd)
+ return;
+
+ m_isEnd = true;
+ return doEnd();
+}
+
+Upstream::Upstream()
+ : m_next(nullptr)
+{
+}
+
+void
+Upstream::appendChain(unique_ptr<Downstream> tail)
+{
+ if (m_next == nullptr) {
+ m_next = std::move(tail);
+ }
+ else {
+ BOOST_ASSERT(dynamic_cast<Transform*>(m_next.get()) != nullptr);
+ static_cast<Transform*>(m_next.get())->appendChain(std::move(tail));
+ }
+}
+
+Source::Source()
+ : m_nModules(1) // source per se is counted as one module
+{
+}
+
+void
+Source::pump()
+{
+ doPump();
+}
+
+Source&
+Source::operator>>(unique_ptr<Transform> transform)
+{
+ transform->setIndex(m_nModules);
+ m_nModules++;
+ this->appendChain(std::move(transform));
+
+ return *this;
+}
+
+void
+Source::operator>>(unique_ptr<Sink> sink)
+{
+ sink->setIndex(m_nModules);
+ m_nModules++;
+ this->appendChain(std::move(sink));
+
+ this->pump();
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn
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
diff --git a/tests/unit-tests/security/transform.t.cpp b/tests/unit-tests/security/transform.t.cpp
new file mode 100644
index 0000000..6999df4
--- /dev/null
+++ b/tests/unit-tests/security/transform.t.cpp
@@ -0,0 +1,56 @@
+/* -*- 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.
+ */
+
+#include "security/transform.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(TestTransform)
+
+BOOST_AUTO_TEST_CASE(SymbolVisibility)
+{
+ transform::BufferSource* bufferSource = nullptr;
+ BOOST_CHECK(bufferSource == nullptr);
+
+ transform::StreamSource* streamSource = nullptr;
+ BOOST_CHECK(streamSource == nullptr);
+
+ transform::StepSource* stepSource = nullptr;
+ BOOST_CHECK(stepSource == nullptr);
+
+ transform::BoolSink* boolSink = nullptr;
+ BOOST_CHECK(boolSink == nullptr);
+
+ transform::StreamSink* streamSink = nullptr;
+ BOOST_CHECK(streamSink == nullptr);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestTransform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/bool-sink.t.cpp b/tests/unit-tests/security/transform/bool-sink.t.cpp
new file mode 100644
index 0000000..4683219
--- /dev/null
+++ b/tests/unit-tests/security/transform/bool-sink.t.cpp
@@ -0,0 +1,63 @@
+/* -*- 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.
+ */
+
+#include "security/transform/bool-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBoolSink)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in1[] = {0x00, 0x01};
+ bool value1 = true;
+ BoolSink sink1(value1);
+ BOOST_CHECK_EQUAL(sink1.write(in1, 1), 1);
+ BOOST_CHECK_EQUAL(sink1.write(in1 + 1, 1), 1);
+ sink1.end();
+ BOOST_CHECK_EQUAL(value1, false);
+ BOOST_CHECK_THROW(sink1.write(in1 + 1, 1), transform::Error);
+
+ uint8_t in2[] = {0x01, 0x00};
+ bool value2 = false;
+ BoolSink sink2(value2);
+ BOOST_CHECK_EQUAL(sink2.write(in2, 1), 1);
+ BOOST_CHECK_EQUAL(sink2.write(in2 + 1, 1), 1);
+ sink2.end();
+ BOOST_CHECK_EQUAL(value2, true);
+ BOOST_CHECK_THROW(sink2.write(in2 + 1, 1), transform::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBoolSink
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/buffer-source.t.cpp b/tests/unit-tests/security/transform/buffer-source.t.cpp
new file mode 100644
index 0000000..151fd96
--- /dev/null
+++ b/tests/unit-tests/security/transform/buffer-source.t.cpp
@@ -0,0 +1,89 @@
+/* -*- 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.
+ */
+
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestBufferSource)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ std::ostringstream os1;
+ bufferSource(in, sizeof(in)) >> streamSink(os1);
+ std::string out1 = os1.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in, in + sizeof(in), out1.begin(), out1.end());
+
+ std::string in2 =
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567";
+
+ std::ostringstream os2;
+ bufferSource(in2) >> streamSink(os2);
+ std::string out2 = os2.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in2.begin(), in2.end(), out2.begin(), out2.end());
+
+ Buffer in3(in, sizeof(in));
+ std::ostringstream os3;
+ bufferSource(in3) >> streamSink(os3);
+ std::string out3 = os3.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in3.begin(), in3.end(), out3.begin(), out3.end());
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestBufferSource
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/step-source.t.cpp b/tests/unit-tests/security/transform/step-source.t.cpp
new file mode 100644
index 0000000..321a3dc
--- /dev/null
+++ b/tests/unit-tests/security/transform/step-source.t.cpp
@@ -0,0 +1,81 @@
+/* -*- 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.
+ */
+
+#include "security/transform/step-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStepSource)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string input =
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567";
+ const uint8_t* buf = reinterpret_cast<const uint8_t*>(input.data());
+
+ std::stringstream os;
+ StepSource ss;
+ ss >> streamSink(os);
+ BOOST_CHECK_EQUAL(ss.write(buf, 320), 320);
+ BOOST_CHECK_EQUAL(ss.write(buf + 320, 320), 320);
+ BOOST_CHECK_EQUAL(ss.write(buf + 640, 320), 320);
+ BOOST_CHECK_EQUAL(ss.write(buf + 960, 320), 320);
+ ss.end();
+ BOOST_REQUIRE_THROW(ss.write(buf + 960, 320), transform::Error);
+ std::string output = os.str();
+ BOOST_CHECK_EQUAL(input, output);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStepSource
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/stream-sink.t.cpp b/tests/unit-tests/security/transform/stream-sink.t.cpp
new file mode 100644
index 0000000..e9185d3
--- /dev/null
+++ b/tests/unit-tests/security/transform/stream-sink.t.cpp
@@ -0,0 +1,60 @@
+/* -*- 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.
+ */
+
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStreamSink)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ uint8_t in[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x20, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ std::ostringstream os;
+ StreamSink sink(os);
+ BOOST_CHECK_EQUAL(sink.write(in, 4), 4);
+ BOOST_CHECK_EQUAL(sink.write(in + 4, 4), 4);
+ BOOST_CHECK_EQUAL(sink.write(in + 8, 4), 4);
+ BOOST_CHECK_EQUAL(sink.write(in + 12, 4), 4);
+ sink.end();
+ std::string out = os.str();
+ BOOST_CHECK_EQUAL_COLLECTIONS(in, in + sizeof(in), out.begin(), out.end());
+ BOOST_CHECK_THROW(sink.write(in + 8, 8), transform::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStreamSink
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/transform/stream-source.t.cpp b/tests/unit-tests/security/transform/stream-source.t.cpp
new file mode 100644
index 0000000..a2f7be3
--- /dev/null
+++ b/tests/unit-tests/security/transform/stream-source.t.cpp
@@ -0,0 +1,75 @@
+/* -*- 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.
+ */
+
+#include "security/transform/stream-source.hpp"
+#include "security/transform/stream-sink.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(Transform)
+BOOST_AUTO_TEST_SUITE(TestStreamSource)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ std::string input =
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "01234567012345670123456701234567 1234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567";
+
+ std::stringstream is(input);
+ std::stringstream os;
+ streamSource(is) >> streamSink(os);
+ std::string output = os.str();
+
+ BOOST_CHECK_EQUAL(input, output);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStreamSource
+BOOST_AUTO_TEST_SUITE_END() // Transform
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace transform
+} // namespace security
+} // namespace ndn