switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / PPI / MultiConnectorMixin.mpp
1 // $Id$
2 //
3 // Copyright (C) 2009
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 //
24 // Contributor(s):
25 //   Stefan Bund <g0dil@berlios.de>
26
27
28 /** \file
29     \brief MultiConnectorMixin Boost.Preprocesser external iteration include */
30
31 #if !BOOST_PP_IS_ITERATING && !defined(MPP_SENF_PPI_MultiConnectorMixin_)
32 #define MPP_SENF_PPI_MultiConnectorMixin_ 1
33
34 // Custom includes
35 #include <boost/preprocessor/iteration/iterate.hpp>
36 #include <boost/preprocessor/control/if.hpp>
37 #include <boost/preprocessor/facilities/empty.hpp>
38 #include <boost/preprocessor/repetition/enum_params.hpp>
39 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
40 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
41 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
42 #include <boost/type_traits/is_base_of.hpp>
43 #include <boost/mpl/and.hpp>
44 #include <boost/mpl/not.hpp>
45 #include <boost/tuple/tuple.hpp>
46
47 //-///////////////////////////mpp.p////////////////////////////////////////
48 #elif BOOST_PP_IS_ITERATING //-////////////////////////////////////////////
49 //-////////////////////////////////////////////////////////////////////////
50 // Local Macros
51
52 // => template <class A0, class A1, ...>
53 #define mpp_TplParams()                                                 \
54     BOOST_PP_IF(BOOST_PP_ITERATION(), mpp_TplParams_, BOOST_PP_EMPTY)()
55 #define mpp_TplParams_()                                                \
56     template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
57
58 // => , class A0, class A1, ...
59 #define mpp_TplParamsKomma()                                            \
60     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
61
62 // => A0 const & a0, A1 const & a1, ...
63 #define mpp_FnParams()                                                  \
64     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
65
66 // => , A0 const & a0, A1 const & a1, ...
67 #define mpp_FnParamsKomma()                                             \
68     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
69
70 // => a0, a1, ...
71 #define mpp_CallParams()                                                \
72     BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
73
74 // => , a0, a1, ...
75 #define mpp_CallParamsKomma()                                           \
76     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
77
78 // Same as above but for outer iteration (in nested file iteration)
79 #define mpp_TplParamsKomma2()                                            \
80     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), class B)
81 #define mpp_FnParams2()                                                  \
82     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, cont & b)
83 #define mpp_FnParamsKomma2()                                             \
84     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & b)
85 #define mpp_CallParams2()                                                \
86     BOOST_PP_ENUM_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
87 #define mpp_CallParamsKomma2()                                           \
88     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
89
90 //-////////////////////////////////////////////////////////////////////////
91 #if BOOST_PP_ITERATION_FLAGS()==1 //-//////////////////////////////////////
92 //-////////////////////////////////////////////////////////////////////////
93 // senf::ppi::module::MultiConnectorMixin member declaration 1..MAX_ARGS
94
95 mpp_TplParams()
96 ConnectorType_ & newConnector( mpp_FnParams() );
97
98 //-////////////////////////////////////////////////////////////////////////
99 #elif BOOST_PP_ITERATION_FLAGS()==2 //-////////////////////////////////////
100 //-////////////////////////////////////////////////////////////////////////
101 // senf::ppi namespace member declaration 1..MAX_ARGS
102
103 // Here the reference to Source::ConnectorType / Target::ConnectorType
104 // works like enable_if, since only MultiConnector modules have those members
105
106 template <class Source, class Target mpp_TplParamsKomma()>
107 typename boost::enable_if<
108     boost::mpl::and_<
109         senf::ppi::module::detail::IsMulticonnectorSource<Source>,
110         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
111     typename Source::ConnectorType & >::type
112 connect(Source & source mpp_FnParamsKomma(), Target & target);
113
114 template <class Source, class Target mpp_TplParamsKomma()>
115 typename boost::enable_if<
116     boost::mpl::and_<
117         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
118         senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
119     typename Target::ConnectorType & >::type
120 connect(Source & source, Target & target mpp_FnParamsKomma());
121
122 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
123         0, \
124         SENF_MULTI_CONNECTOR_MAX_ARGS, \
125         SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
126         4 ))
127 #include BOOST_PP_ITERATE()
128
129 //-////////////////////////////////////////////////////////////////////////
130 #elif BOOST_PP_ITERATION_FLAGS()==4 //-////////////////////////////////////
131 //-////////////////////////////////////////////////////////////////////////
132 // senf::ppi namespace member declaration 1..MAX_ARGS x 1..MAX_ARGS
133
134 template <class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
135 typename boost::enable_if<
136     boost::mpl::and_<
137         boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
138         boost::is_base_of<connector::InputConnector, typename Target::ConnectorType> >,
139     boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
140 connect(Source & source mpp_FnParamsKomma(), Target & target mpp_FnParamsKomma2());
141
142 //-////////////////////////////////////////////////////////////////////////
143 #elif BOOST_PP_ITERATION_FLAGS()==8 //-////////////////////////////////////
144 //-////////////////////////////////////////////////////////////////////////
145 // senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..MAX_ARGS
146
147 template <class Module mpp_TplParamsKomma()>
148 static typename Module::ConnectorType &
149 newConnector(Module & module mpp_FnParamsKomma());
150
151 //-////////////////////////////////////////////////////////////////////////
152 #elif BOOST_PP_ITERATION_FLAGS()==3 //-////////////////////////////////////
153 //-////////////////////////////////////////////////////////////////////////
154 // Implementation 1..MAX_ARGS
155
156 //-/////////////////////////////////////////////////////////////////////////////////////////////////
157 // Map container
158
159 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
160 mpp_TplParams()
161 prefix_ ConnectorType_ &
162 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
163 newConnector(mpp_FnParams())
164 {
165     std::auto_ptr<ConnectorType_> conn (new detail::MultiConnectorWrapper<Self_,ConnectorType_>);
166     KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
167     return * connectors_.insert(key, conn).first->second;
168 }
169
170 //-/////////////////////////////////////////////////////////////////////////////////////////////////
171 // Vector container
172
173 template <class Self_, class ConnectorType_, class ContainerType_>
174 mpp_TplParams()
175 prefix_ ConnectorType_ &
176 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
177 newConnector(mpp_FnParams())
178 {
179     connectors_.push_back(new detail::MultiConnectorWrapper<Self_,ConnectorType_>);
180     ConnectorType_ & conn (connectors_.back());
181     try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
182     catch (...) { disconnected(conn); throw; }
183     return conn;
184 }
185
186 //-/////////////////////////////////////////////////////////////////////////////////////////////////
187 // User managed container
188
189 template <class Self_, class ConnectorType_>
190 mpp_TplParams()
191 prefix_ ConnectorType_ &
192 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
193 newConnector(mpp_FnParams())
194 {
195     std::auto_ptr<ConnectorType_> cp (new detail::MultiConnectorWrapper<Self_,ConnectorType_>);
196     ConnectorType_ & cref (*cp);
197     static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
198     return cref;
199 }
200
201 //-/////////////////////////////////////////////////////////////////////////////////////////////////
202 // senf::ppi::connect
203
204 template <class Source, class Target mpp_TplParamsKomma()>
205 typename boost::enable_if<
206     boost::mpl::and_<
207         senf::ppi::module::detail::IsMulticonnectorSource<Source>,
208         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
209     typename Source::ConnectorType & >::type
210 senf::ppi::connect(Source & source mpp_FnParamsKomma(), Target & target)
211 {
212     typename Source::ConnectorType & c (
213         module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
214     connect(c, target);
215     return c;
216 }
217
218 template <class Source, class Target mpp_TplParamsKomma()>
219 typename boost::enable_if<
220     boost::mpl::and_<
221         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
222         senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
223     typename Target::ConnectorType & >::type
224 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
225 {
226     typename Target::ConnectorType & c (
227         module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma()));
228     connect(source, c);
229     return c;
230 }
231
232 //-/////////////////////////////////////////////////////////////////////////////////////////////////
233 // senf::ppi::module::detail::MultiConnectorMixinAccess members
234
235 template <class Module mpp_TplParamsKomma()>
236 typename Module::ConnectorType &
237 senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector(
238     Module & module mpp_FnParamsKomma())
239 {
240     return module.newConnector(mpp_CallParams());
241 }
242
243 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
244         0, \
245         SENF_MULTI_CONNECTOR_MAX_ARGS, \
246         SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
247         5 ))
248 #include BOOST_PP_ITERATE()
249
250 //-/////////////////////////////////////////////////////////////////////////////////////////////////
251 #elif BOOST_PP_ITERATION_FLAGS()==5 //-////////////////////////////////////
252 //-////////////////////////////////////////////////////////////////////////
253 // Implementation 1..MAX_ARGS x 1..MAX_ARGS
254
255 template <class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
256 typename boost::enable_if<
257     boost::mpl::and_<
258         boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
259         boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType> >,
260     boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
261 senf::ppi::connect(Source & source mpp_FnParamsKomma(), Target & target mpp_FnParamsKomma2())
262 {
263     typename Source::ConnectorType & s (
264         module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
265     typename Target::ConnectorType & t (
266         module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma2()));
267     connect(s,t);
268     return boost::tie(s,t);
269 }
270
271 //-////////////////////////////////////////////////////////////////////////
272 #endif //-/////////////////////////////////////////////////////////////////
273 //-////////////////////////////////////////////////////////////////////////
274 // Undefine local Macros
275
276 #undef mpp_CallParamsKomma2
277 #undef mpp_CallParams2
278 #undef mpp_FnParamsKomma2
279 #undef mpp_FnParams2
280 #undef mpp_TplParamsKomma2
281 #undef mpp_CallParamsKomma
282 #undef mpp_CallParams
283 #undef mpp_FnParamsKomma
284 #undef mpp_FnParams
285 #undef mpp_TplParamsKomma
286 #undef mpp_TplParams_
287 #undef mpp_TplParams
288
289 //-////////////////////////////////////////////////////////////////////////
290 /*
291  (save-excursion (re-search-backward "^// Undefine local Macros")
292  (forward-line 1) (delete-region (point) (progn (search-forward
293  "//-////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
294  (e (progn (insert (save-excursion (re-search-backward
295  "^// Local Macros") (search-forward "#define") (beginning-of-line)
296  (buffer-substring (point) (progn (search-forward "//-////")
297  (search-backward "#define") (forward-line 1) (point))))) (point))))
298  (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
299  t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
300  "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z0-9_]")
301  (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
302  1))))
303 */
304 //-////////////////////////////////////////////////////////////////////////
305 #endif //-/////////////////////////////////////////////////////////////////
306 //-///////////////////////////mpp.e////////////////////////////////////////
307
308 \f
309 // Local Variables:
310 // mode: c++
311 // fill-column: 100
312 // comment-column: 40
313 // c-file-style: "senf"
314 // indent-tabs-mode: nil
315 // ispell-local-dictionary: "american"
316 // compile-command: "scons -u test"
317 // End: