ndnboost: Include boost::iostreams for internal use.
diff --git a/include/ndnboost/iostreams/filter/symmetric.hpp b/include/ndnboost/iostreams/filter/symmetric.hpp
new file mode 100644
index 0000000..9c59900
--- /dev/null
+++ b/include/ndnboost/iostreams/filter/symmetric.hpp
@@ -0,0 +1,310 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2003-2007 Jonathan Turkanis
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
+
+// See http://www.boost.org/libs/iostreams for documentation.
+
+// Contains the definitions of the class templates symmetric_filter,
+// which models DualUseFilter based on a model of the Symmetric Filter.
+
+//
+// Roughly, a Symmetric Filter is a class type with the following interface:
+//
+// struct symmetric_filter {
+// typedef xxx char_type;
+//
+// bool filter( const char*& begin_in, const char* end_in,
+// char*& begin_out, char* end_out, bool flush )
+// {
+// // Consume as many characters as possible from the interval
+// // [begin_in, end_in), without exhausting the output range
+// // [begin_out, end_out). If flush is true, write as mush output
+// // as possible.
+// // A return value of true indicates that filter should be called
+// // again. More precisely, if flush is false, a return value of
+// // false indicates that the natural end of stream has been reached
+// // and that all filtered data has been forwarded; if flush is
+// // true, a return value of false indicates that all filtered data
+// // has been forwarded.
+// }
+// void close() { /* Reset filter's state. */ }
+// };
+//
+// Symmetric Filter filters need not be CopyConstructable.
+//
+
+#ifndef NDNBOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED
+#define NDNBOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <ndnboost/assert.hpp>
+#include <memory> // allocator, auto_ptr.
+#include <ndnboost/config.hpp> // NDNBOOST_DEDUCED_TYPENAME.
+#include <ndnboost/iostreams/char_traits.hpp>
+#include <ndnboost/iostreams/constants.hpp> // buffer size.
+#include <ndnboost/iostreams/detail/buffer.hpp>
+#include <ndnboost/iostreams/detail/char_traits.hpp>
+#include <ndnboost/iostreams/detail/config/limits.hpp>
+#include <ndnboost/iostreams/detail/template_params.hpp>
+#include <ndnboost/iostreams/traits.hpp>
+#include <ndnboost/iostreams/operations.hpp> // read, write.
+#include <ndnboost/iostreams/pipeline.hpp>
+#include <ndnboost/preprocessor/iteration/local.hpp>
+#include <ndnboost/preprocessor/punctuation/comma_if.hpp>
+#include <ndnboost/preprocessor/repetition/enum_binary_params.hpp>
+#include <ndnboost/preprocessor/repetition/enum_params.hpp>
+#include <ndnboost/shared_ptr.hpp>
+
+// Must come last.
+#include <ndnboost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
+
+namespace ndnboost { namespace iostreams {
+
+template< typename SymmetricFilter,
+ typename Alloc =
+ std::allocator<
+ NDNBOOST_DEDUCED_TYPENAME char_type_of<SymmetricFilter>::type
+ > >
+class symmetric_filter {
+public:
+ typedef typename char_type_of<SymmetricFilter>::type char_type;
+ typedef NDNBOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type;
+ typedef std::basic_string<char_type, traits_type, Alloc> string_type;
+ struct category
+ : dual_use,
+ filter_tag,
+ multichar_tag,
+ closable_tag
+ { };
+
+ // Expands to a sequence of ctors which forward to impl.
+ #define NDNBOOST_PP_LOCAL_MACRO(n) \
+ NDNBOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \
+ explicit symmetric_filter( \
+ int buffer_size NDNBOOST_PP_COMMA_IF(n) \
+ NDNBOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \
+ : pimpl_(new impl(buffer_size NDNBOOST_PP_COMMA_IF(n) \
+ NDNBOOST_PP_ENUM_PARAMS(n, t))) \
+ { NDNBOOST_ASSERT(buffer_size > 0); } \
+ /**/
+ #define NDNBOOST_PP_LOCAL_LIMITS (0, NDNBOOST_IOSTREAMS_MAX_FORWARDING_ARITY)
+ #include NDNBOOST_PP_LOCAL_ITERATE()
+ #undef NDNBOOST_PP_LOCAL_MACRO
+
+ template<typename Source>
+ std::streamsize read(Source& src, char_type* s, std::streamsize n)
+ {
+ using namespace std;
+ if (!(state() & f_read))
+ begin_read();
+
+ buffer_type& buf = pimpl_->buf_;
+ int status = (state() & f_eof) != 0 ? f_eof : f_good;
+ char_type *next_s = s,
+ *end_s = s + n;
+ while (true)
+ {
+ // Invoke filter if there are unconsumed characters in buffer or if
+ // filter must be flushed.
+ bool flush = status == f_eof;
+ if (buf.ptr() != buf.eptr() || flush) {
+ const char_type* next = buf.ptr();
+ bool done =
+ !filter().filter(next, buf.eptr(), next_s, end_s, flush);
+ buf.ptr() = buf.data() + (next - buf.data());
+ if (done)
+ return detail::check_eof(
+ static_cast<std::streamsize>(next_s - s)
+ );
+ }
+
+ // If no more characters are available without blocking, or
+ // if read request has been satisfied, return.
+ if ( (status == f_would_block && buf.ptr() == buf.eptr()) ||
+ next_s == end_s )
+ {
+ return static_cast<std::streamsize>(next_s - s);
+ }
+
+ // Fill buffer.
+ if (status == f_good)
+ status = fill(src);
+ }
+ }
+
+ template<typename Sink>
+ std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
+ {
+ if (!(state() & f_write))
+ begin_write();
+
+ buffer_type& buf = pimpl_->buf_;
+ const char_type *next_s, *end_s;
+ for (next_s = s, end_s = s + n; next_s != end_s; ) {
+ if (buf.ptr() == buf.eptr() && !flush(snk))
+ break;
+ if(!filter().filter(next_s, end_s, buf.ptr(), buf.eptr(), false)) {
+ flush(snk);
+ break;
+ }
+ }
+ return static_cast<std::streamsize>(next_s - s);
+ }
+
+ template<typename Sink>
+ void close(Sink& snk, NDNBOOST_IOS::openmode mode)
+ {
+ if (mode == NDNBOOST_IOS::out) {
+
+ if (!(state() & f_write))
+ begin_write();
+
+ // Repeatedly invoke filter() with no input.
+ try {
+ buffer_type& buf = pimpl_->buf_;
+ char_type dummy;
+ const char_type* end = &dummy;
+ bool again = true;
+ while (again) {
+ if (buf.ptr() != buf.eptr())
+ again = filter().filter( end, end, buf.ptr(),
+ buf.eptr(), true );
+ flush(snk);
+ }
+ } catch (...) {
+ try { close_impl(); } catch (...) { }
+ throw;
+ }
+ close_impl();
+ } else {
+ close_impl();
+ }
+ }
+ SymmetricFilter& filter() { return *pimpl_; }
+ string_type unconsumed_input() const;
+
+// Give impl access to buffer_type on Tru64
+#if !NDNBOOST_WORKAROUND(__DECCXX_VER, NDNBOOST_TESTED_AT(60590042))
+ private:
+#endif
+ typedef detail::buffer<char_type, Alloc> buffer_type;
+private:
+ buffer_type& buf() { return pimpl_->buf_; }
+ const buffer_type& buf() const { return pimpl_->buf_; }
+ int& state() { return pimpl_->state_; }
+ void begin_read();
+ void begin_write();
+
+ template<typename Source>
+ int fill(Source& src)
+ {
+ std::streamsize amt = iostreams::read(src, buf().data(), buf().size());
+ if (amt == -1) {
+ state() |= f_eof;
+ return f_eof;
+ }
+ buf().set(0, amt);
+ return amt != 0 ? f_good : f_would_block;
+ }
+
+ // Attempts to write the contents of the buffer the given Sink.
+ // Returns true if at least on character was written.
+ template<typename Sink>
+ bool flush(Sink& snk)
+ {
+ typedef typename iostreams::category_of<Sink>::type category;
+ typedef is_convertible<category, output> can_write;
+ return flush(snk, can_write());
+ }
+
+ template<typename Sink>
+ bool flush(Sink& snk, mpl::true_)
+ {
+ std::streamsize amt =
+ static_cast<std::streamsize>(buf().ptr() - buf().data());
+ std::streamsize result =
+ ndnboost::iostreams::write(snk, buf().data(), amt);
+ if (result < amt && result > 0)
+ traits_type::move(buf().data(), buf().data() + result, amt - result);
+ buf().set(amt - result, buf().size());
+ return result != 0;
+ }
+
+ template<typename Sink>
+ bool flush(Sink&, mpl::false_) { return true;}
+
+ void close_impl();
+
+ enum flag_type {
+ f_read = 1,
+ f_write = f_read << 1,
+ f_eof = f_write << 1,
+ f_good,
+ f_would_block
+ };
+
+ struct impl : SymmetricFilter {
+
+ // Expands to a sequence of ctors which forward to SymmetricFilter.
+ #define NDNBOOST_PP_LOCAL_MACRO(n) \
+ NDNBOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \
+ impl( int buffer_size NDNBOOST_PP_COMMA_IF(n) \
+ NDNBOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \
+ : SymmetricFilter(NDNBOOST_PP_ENUM_PARAMS(n, t)), \
+ buf_(buffer_size), state_(0) \
+ { } \
+ /**/
+ #define NDNBOOST_PP_LOCAL_LIMITS (0, NDNBOOST_IOSTREAMS_MAX_FORWARDING_ARITY)
+ #include NDNBOOST_PP_LOCAL_ITERATE()
+ #undef NDNBOOST_PP_LOCAL_MACRO
+
+ buffer_type buf_;
+ int state_;
+ };
+
+ shared_ptr<impl> pimpl_;
+};
+NDNBOOST_IOSTREAMS_PIPABLE(symmetric_filter, 2)
+
+//------------------Implementation of symmetric_filter----------------//
+
+template<typename SymmetricFilter, typename Alloc>
+void symmetric_filter<SymmetricFilter, Alloc>::begin_read()
+{
+ NDNBOOST_ASSERT(!(state() & f_write));
+ state() |= f_read;
+ buf().set(0, 0);
+}
+
+template<typename SymmetricFilter, typename Alloc>
+void symmetric_filter<SymmetricFilter, Alloc>::begin_write()
+{
+ NDNBOOST_ASSERT(!(state() & f_read));
+ state() |= f_write;
+ buf().set(0, buf().size());
+}
+
+template<typename SymmetricFilter, typename Alloc>
+void symmetric_filter<SymmetricFilter, Alloc>::close_impl()
+{
+ state() = 0;
+ buf().set(0, 0);
+ filter().close();
+}
+
+template<typename SymmetricFilter, typename Alloc>
+typename symmetric_filter<SymmetricFilter, Alloc>::string_type
+symmetric_filter<SymmetricFilter, Alloc>::unconsumed_input() const
+{ return string_type(buf().ptr(), buf().eptr()); }
+
+//----------------------------------------------------------------------------//
+
+} } // End namespaces iostreams, boost.
+
+#include <ndnboost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
+
+#endif // #ifndef NDNBOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED