1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 #ifndef BOOST_IOSTREAMS_PIPABLE_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_PIPABLE_HPP_INCLUDED
10 
11 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
12 # pragma once
13 #endif
14 
15 #include <boost/config.hpp> // BOOST_MSVC.
16 #include <boost/detail/workaround.hpp>
17 #include <boost/iostreams/detail/template_params.hpp>
18 #include <boost/iostreams/traits.hpp>
19 #include <boost/mpl/bool.hpp>
20 #include <boost/preprocessor/punctuation/comma_if.hpp>
21 #include <boost/preprocessor/repetition/enum_params.hpp>
22 #include <boost/static_assert.hpp>
23 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
24 # include <boost/type_traits/is_base_and_derived.hpp>
25 #endif
26 
27 #define BOOST_IOSTREAMS_PIPABLE(filter, arity) \
28     template< BOOST_PP_ENUM_PARAMS(arity, typename T) \
29               BOOST_PP_COMMA_IF(arity) typename Component> \
30     ::boost::iostreams::pipeline< \
31         ::boost::iostreams::detail::pipeline_segment< \
32             filter BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T) \
33         >, \
34         Component \
35     > operator|( const filter BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T)& f, \
36                  const Component& c ) \
37     { \
38         typedef ::boost::iostreams::detail::pipeline_segment< \
39                     filter BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T) \
40                 > segment; \
41         return ::boost::iostreams::pipeline<segment, Component> \
42                    (segment(f), c); \
43     } \
44     /**/
45 
46 namespace boost { namespace iostreams {
47 
48 template<typename Pipeline, typename Component>
49 struct pipeline;
50 
51 namespace detail {
52 
53 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
54     struct pipeline_base { };
55 
56     template<typename T>
57     struct is_pipeline
58         : is_base_and_derived<pipeline_base, T>
59         { };
60 #endif
61 #if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
62     template<typename T>
63     struct is_pipeline : mpl::false_ { };
64 
65     template<typename Pipeline, typename Component>
66     struct is_pipeline< pipeline<Pipeline, Component> > : mpl::true_ { };
67 #endif
68 
69 template<typename Component>
70 class pipeline_segment
71 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
72     : pipeline_base
73 #endif
74 {
75 public:
pipeline_segment(const Component & component)76     pipeline_segment(const Component& component)
77         : component_(component)
78         { }
79     template<typename Fn>
for_each(Fn fn) const80     void for_each(Fn fn) const { fn(component_); }
81     template<typename Chain>
push(Chain & chn) const82     void push(Chain& chn) const { chn.push(component_); }
83 private:
84     pipeline_segment operator=(const pipeline_segment&);
85     const Component& component_;
86 };
87 
88 } // End namespace detail.
89 
90 //------------------Definition of Pipeline------------------------------------//
91 
92 template<typename Pipeline, typename Component>
93 struct pipeline : Pipeline {
94     typedef Pipeline   pipeline_type;
95     typedef Component  component_type;
pipelineboost::iostreams::pipeline96     pipeline(const Pipeline& p, const Component& component)
97         : Pipeline(p), component_(component)
98         { }
99     template<typename Fn>
for_eachboost::iostreams::pipeline100     void for_each(Fn fn) const
101     {
102         Pipeline::for_each(fn);
103         fn(component_);
104     }
105     template<typename Chain>
pushboost::iostreams::pipeline106     void push(Chain& chn) const
107     {
108         Pipeline::push(chn);
109         chn.push(component_);
110     }
tailboost::iostreams::pipeline111     const Pipeline& tail() const { return *this; }
headboost::iostreams::pipeline112     const Component& head() const { return component_; }
113 private:
114     pipeline operator=(const pipeline&);
115     const Component& component_;
116 };
117 
118 template<typename Pipeline, typename Filter, typename Component>
119 pipeline<pipeline<Pipeline, Filter>, Component>
operator |(const pipeline<Pipeline,Filter> & p,const Component & cmp)120 operator|(const pipeline<Pipeline, Filter>& p, const Component& cmp)
121 {
122     BOOST_STATIC_ASSERT(is_filter<Filter>::value);
123     return pipeline<pipeline<Pipeline, Filter>, Component>(p, cmp);
124 }
125 
126 } } // End namespaces iostreams, boost.
127 
128 #endif // #ifndef BOOST_IOSTREAMS_PIPABLE_HPP_INCLUDED
129