Move sourcecode into 'senf/' directory
[senf.git] / senf / PPI / MultiConnectorMixin.mpp
1 // $Id$
2 //
3 // Copyright (C) 2009 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief MultiConnectorMixin Boost.Preprocesser external iteration include */
25
26 #if !BOOST_PP_IS_ITERATING && !defined(MPP_SENF_PPI_MultiConnectorMixin_)
27 #define MPP_SENF_PPI_MultiConnectorMixin_ 1
28
29 // Custom includes
30 #include <boost/preprocessor/iteration/iterate.hpp>
31 #include <boost/preprocessor/control/if.hpp>
32 #include <boost/preprocessor/facilities/empty.hpp> 
33 #include <boost/preprocessor/repetition/enum_params.hpp>
34 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
35 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
36 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> 
37 #include <boost/type_traits/is_base_of.hpp>
38
39 // ///////////////////////////mpp.p////////////////////////////////////////
40 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
41 // ////////////////////////////////////////////////////////////////////////
42 // Local Macros
43
44 #define mpp_TplParams()                                                 \
45     BOOST_PP_IF(                                                        \
46         BOOST_PP_ITERATION(),                                           \
47         mpp_TplParams_,                                                 \
48         BOOST_PP_EMPTY)()
49 #define mpp_TplParams_()                                                \
50     template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
51     
52 #define mpp_TplParamsKomma()                                            \
53     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
54 #define mpp_FnParams()                                                  \
55     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
56 #define mpp_FnParamsKomma()                                             \
57     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
58 #define mpp_CallParams()                                                \
59     BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
60 #define mpp_CallParamsKomma()                                           \
61     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
62
63 // ////////////////////////////////////////////////////////////////////////
64 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
65 // ////////////////////////////////////////////////////////////////////////
66 // MultiConnectorMixin member declaration
67
68 mpp_TplParams()
69 ConnectorType_ & newConnector( mpp_FnParams() );
70
71 template <class Source, class Target mpp_TplParamsKomma()>
72 friend typename boost::enable_if<
73         boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
74         typename Source::ConnectorType & >::type
75     senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma());
76
77 template <class Source, class Target mpp_TplParamsKomma()>
78 friend typename boost::enable_if<
79         boost::is_base_of<connector::InputConnector, typename Target::ConnectorType>,
80         typename Target::ConnectorType & >::type
81     senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma());
82
83 // ////////////////////////////////////////////////////////////////////////
84 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
85 // ////////////////////////////////////////////////////////////////////////
86 // senf::ppi namespace member declaration
87
88 template <class Source, class Target mpp_TplParamsKomma()>
89 typename boost::enable_if<
90     boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
91     typename Source::ConnectorType & >::type
92 connect(Source & source, Target & target mpp_FnParamsKomma());
93
94 template <class Source, class Target mpp_TplParamsKomma()>
95 typename boost::enable_if<
96     boost::is_base_of<connector::InputConnector, typename Target::ConnectorType>,
97     typename Target::ConnectorType & >::type
98 connect(Source & source, Target & target mpp_FnParamsKomma());
99
100 // ////////////////////////////////////////////////////////////////////////
101 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
102 // ////////////////////////////////////////////////////////////////////////
103 // Implementation
104
105 ////////////////////////////////////////
106 // Map container
107
108 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
109 mpp_TplParams()
110 prefix_ ConnectorType_ &
111 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
112 newConnector(mpp_FnParams())
113 {
114     std::auto_ptr<ConnectorType_> conn (new ConnectorType_);
115     KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
116     return * connectors_.insert(key, conn).first->second;
117 }
118
119 ////////////////////////////////////////
120 // Vector container
121
122 template <class Self_, class ConnectorType_, class ContainerType_>
123 mpp_TplParams()
124 prefix_ ConnectorType_ &
125 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
126 newConnector(mpp_FnParams())
127 {
128     connectors_.push_back(new ConnectorType_);
129     ConnectorType_ & conn (connectors_.back());
130     try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
131     catch (...) { connectors_.pop_back(); throw; }
132     return conn;
133 }
134
135 ////////////////////////////////////////
136 // User managed container
137
138 template <class Self_, class ConnectorType_>
139 mpp_TplParams()
140 prefix_ ConnectorType_ &
141 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
142 newConnector(mpp_FnParams())
143 {
144     std::auto_ptr<ConnectorType_> cp (new ConnectorType_);
145     ConnectorType_ & cref (*cp);
146     static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
147     return cref;
148 }
149
150 ////////////////////////////////////////
151 // senf::ppi::connect
152
153 template <class Source, class Target mpp_TplParamsKomma()>
154 typename boost::enable_if<
155     boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
156     typename Source::ConnectorType & >::type
157 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
158 {
159     typename Source::ConnectorType & c (source.newConnector(mpp_CallParams()));
160     connect(c, target);
161     return c;
162 }
163
164 template <class Source, class Target mpp_TplParamsKomma()>
165 typename boost::enable_if<
166     boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType>,
167     typename Target::ConnectorType & >::type
168 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
169 {
170     typename Target::ConnectorType & c (target.newConnector(mpp_CallParams()));
171     connect(source, c);
172     return c;
173 }
174
175 // ////////////////////////////////////////////////////////////////////////
176 #endif // /////////////////////////////////////////////////////////////////
177 // ////////////////////////////////////////////////////////////////////////
178 // Undefine local Macros
179
180 #undef mpp_CallParamsKomma
181 #undef mpp_CallParams
182 #undef mpp_FnParamsKomma
183 #undef mpp_FnParams
184 #undef mpp_TplParamsKomma
185 #undef mpp_TplParams_
186 #undef mpp_TplParams
187             
188 // ////////////////////////////////////////////////////////////////////////
189 /*
190  (save-excursion (re-search-backward "^// Undefine local Macros")
191  (forward-line 1) (delete-region (point) (progn (search-forward
192  "// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
193  (e (progn (insert (save-excursion (re-search-backward 
194  "^// Local Macros") (search-forward "#define") (beginning-of-line)
195  (buffer-substring (point) (progn (search-forward "// ////")
196  (search-backward "#define") (forward-line 1) (point))))) (point))))
197  (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
198  t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
199  "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z_]")
200  (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
201  1))))
202 */
203 // ////////////////////////////////////////////////////////////////////////
204 #endif // /////////////////////////////////////////////////////////////////
205 // ///////////////////////////mpp.e////////////////////////////////////////
206
207 \f
208 // Local Variables:
209 // mode: c++
210 // fill-column: 100
211 // comment-column: 40
212 // c-file-style: "senf"
213 // indent-tabs-mode: nil
214 // ispell-local-dictionary: "american"
215 // compile-command: "scons -u test"
216 // End: