0e2b58fd63b241d80570c149eb6e010496a09707
[senf.git] / Socket / SocketPolicy.ih
1 // $Id$
2 //
3 // Copyright (C) 2006 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 Policy Framework internal header
25  */
26
27 #ifndef IH_SocketPolicy_
28 #define IH_SocketPolicy_ 1
29
30 // Custom includes
31 #include <boost/preprocessor/seq/for_each.hpp>
32 #include <boost/preprocessor/seq/for_each_i.hpp>
33 #include <boost/preprocessor/seq/size.hpp>
34 #include <boost/preprocessor/seq/pop_front.hpp>
35 #include <boost/preprocessor/punctuation/comma_if.hpp>
36 #include <boost/preprocessor/repetition/enum_params.hpp>
37 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
38 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
39 #include <boost/preprocessor/cat.hpp>
40 #include <boost/preprocessor/seq/elem.hpp>
41 #include <boost/preprocessor/arithmetic/dec.hpp>
42 #include <boost/preprocessor/iteration/local.hpp>
43 #include <boost/preprocessor/control/if.hpp>
44 #include <boost/preprocessor/comparison/equal.hpp>
45
46 #include <boost/type_traits.hpp>
47 #include <boost/mpl/vector.hpp>
48 #include <boost/mpl/fold.hpp>
49 #include <boost/mpl/if.hpp>
50 #include <boost/mpl/and.hpp>
51 #include <boost/utility.hpp> // for enable_if
52
53 ///////////////////////////////ih.p////////////////////////////////////////
54
55 /// \cond disabled
56 // Hide this code from doxygen
57
58 namespace senf {
59
60 #   define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES )
61     
62 #   define SP_DeclareAlias(x1,x2,SomePolicy)                                             \
63         typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
64
65     BOOST_PP_SEQ_FOR_EACH( SP_DeclareAlias, , SENF_SOCKET_POLICIES )
66
67 #   undef SP_DeclareAlias
68         
69     struct SocketPolicyBase
70     {
71         virtual ~SocketPolicyBase() {}
72
73 #       define SP_Declare(x1,x2,SomePolicy)                                                     \
74             virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const = 0;
75
76         BOOST_PP_SEQ_FOR_EACH( SP_Declare, , SENF_SOCKET_POLICIES )
77
78 #       undef SP_Declare
79     };
80
81 #   define SP_TemplateArgs(x1,x2,n,SomePolicy)                                  \
82         BOOST_PP_COMMA_IF( n )                                                  \
83         class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base)
84
85     template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
86     struct SocketPolicy
87         : public SocketPolicyBase
88     {
89 #   define SP_DeclarePolicyMember(x1,x2,SomePolicy)                                     \
90         typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy;                                  \
91         SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_);                        \
92         BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const     \
93             { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
94
95         BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES )
96 #   undef SP_DeclarePolicyMember
97
98         static void checkBaseOf(SocketPolicyBase const & other);
99     };
100
101 #   undef SP_TemplateArgs
102
103 namespace impl {
104
105     struct nil {};
106
107     template <int N>
108     struct SocketPolicy_rv
109     { int v[N+1]; };
110     
111     template <class Base, class Policy, int N>
112     struct MakeSocketPolicy_merge
113     {};
114
115 #   define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy)            \
116         BOOST_PP_COMMA_IF( m )                                                  \
117         BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy )
118
119 #    define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) )
120 #    define BOOST_PP_LOCAL_MACRO(n)                                                                                     \
121         SocketPolicy_rv<n> MakeSocketPolicy_merge_(BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*);  \
122                                                                                                                         \
123         template <class Base, class Policy>                                                                             \
124         struct MakeSocketPolicy_merge<Base,Policy,sizeof(SocketPolicy_rv<n>)>                                           \
125         {                                                                                                               \
126             typedef SocketPolicy<                                                                                       \
127                BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, n, SENF_SOCKET_POLICIES )              \
128                > type;                                                                                                  \
129         };
130
131 #   include BOOST_PP_LOCAL_ITERATE()
132
133 #   undef SP_DeclareMakeSocketPolicy_merge_member
134
135     struct MakeSocketPolicy_fold
136     {
137         template <class Base, class Policy>
138         struct apply
139             : MakeSocketPolicy_merge<Base,
140                                      Policy,
141                                      sizeof(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
142         {};
143
144         template <class Base>
145         struct apply<Base,nil>
146         {
147             typedef Base type;
148         };
149     };
150
151     template <class Base, class Vector>
152     struct MakeSocketPolicy_impl
153     {
154         typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy;
155     };
156
157 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)      \
158         BOOST_PP_COMMA_IF( n )                          \
159         typename Base::SomePolicy *
160
161     template <class Base>
162     SocketPolicy_rv<1> SocketPolicy_checkcompat_(
163         BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) );
164
165 #   undef SP_DeclareArguments
166
167     template <class Base>
168     SocketPolicy_rv<2> SocketPolicy_checkcompat_( ... );
169
170     template <int Size>
171     struct SocketPolicy_checkcompat
172         : public boost::false_type
173     {};
174
175     template<>
176     struct SocketPolicy_checkcompat<sizeof(SocketPolicy_rv<1>)>
177         : public boost::true_type
178     {};
179
180
181 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)      \
182         BOOST_PP_COMMA_IF( n )                          \
183         static_cast<typename Derived::SomePolicy *>(0)
184
185     template <class Base, class Derived>
186     struct SocketPolicy_compatibility
187         : public SocketPolicy_checkcompat< sizeof(
188             SocketPolicy_checkcompat_<Base>(
189                 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) >
190     {};
191
192 } // namespace impl
193
194     template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N, class T, senf::impl::nil ) >
195     class MakeSocketPolicy
196         : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
197                                   impl::MakeSocketPolicy_impl< T0, boost::mpl::vector< BOOST_PP_ENUM_SHIFTED_PARAMS( SENF_SOCKET_POLICIES_N, T ) > >,
198                                   impl::MakeSocketPolicy_impl< SocketPolicy<>,
199                                                                boost::mpl::vector< BOOST_PP_ENUM_PARAMS( SENF_SOCKET_POLICIES_N, T ) > > >::type
200     {};
201
202     template <class BasePolicy, class DerivedPolicy>
203     struct SocketPolicyIsBaseOf
204         : public boost::mpl::if_< boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >,
205                                                     boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >,
206                                   impl::SocketPolicy_compatibility<BasePolicy,DerivedPolicy>,
207                                   boost::false_type >::type
208     {};
209
210 #   define SP_DefineConditions(x1,x2,SomePolicy)                                                \
211         template <class Policy, class Trait>                                                    \
212         struct BOOST_PP_CAT(SomePolicy,Is)                                                      \
213             : public boost::is_convertible< typename Policy::SomePolicy*, Trait* >              \
214         {};                                                                                     \
215                                                                                                 \
216         template <class Policy, class Trait>                                                    \
217         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is)                                     \
218             : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait> >              \
219         {};                                                                                     \
220                                                                                                 \
221         template <class Policy, class Trait>                                                    \
222         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot)                                  \
223             : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait>::value >   \
224         {};
225
226     BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES )
227
228 #   undef SP_DefineConditions
229
230 }
231
232 /// \endcond
233
234 ///////////////////////////////ih.e////////////////////////////////////////
235 #endif
236
237 \f
238 // Local Variables:
239 // mode: c++
240 // c-file-style: "senf"
241 // End: