git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@129 270642c3-0616-0410...
[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 #ifndef IH_SocketPolicy_
24 #define IH_SocketPolicy_ 1
25
26 // Custom includes
27 #include <boost/preprocessor/seq/for_each.hpp>
28 #include <boost/preprocessor/seq/for_each_i.hpp>
29 #include <boost/preprocessor/seq/size.hpp>
30 #include <boost/preprocessor/seq/pop_front.hpp>
31 #include <boost/preprocessor/punctuation/comma_if.hpp>
32 #include <boost/preprocessor/repetition/enum_params.hpp>
33 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
34 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
35 #include <boost/preprocessor/cat.hpp>
36 #include <boost/preprocessor/seq/elem.hpp>
37 #include <boost/preprocessor/arithmetic/dec.hpp>
38 #include <boost/preprocessor/iteration/local.hpp>
39 #include <boost/preprocessor/control/if.hpp>
40 #include <boost/preprocessor/comparison/equal.hpp>
41
42 #include <boost/type_traits.hpp>
43 #include <boost/mpl/vector.hpp>
44 #include <boost/mpl/fold.hpp>
45 #include <boost/mpl/if.hpp>
46 #include <boost/mpl/and.hpp>
47 #include <boost/utility.hpp> // for enable_if
48
49 ///////////////////////////////ih.p////////////////////////////////////////
50
51 namespace satcom {
52 namespace lib {
53
54 #   define SATLIB_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SATLIB_SOCKET_POLICIES )
55     
56     // This REALLY is bad ... but we just need an Address member in
57     // AddressingPolicyBase as long as ClientSocketHandle /
58     // ServerSocketHandle don't make use of enable_if for each and
59     // every member they define ...
60
61     struct AddressingPolicyBase
62     {
63         virtual ~ AddressingPolicyBase() {}
64         
65         class Address 
66         {
67         private:
68             Address();
69         };
70     };
71
72 #   define SP_DeclareBase(x1,x2,SomePolicy)                                             \
73         struct BOOST_PP_CAT(SomePolicy,Base)                                            \
74         { virtual ~ BOOST_PP_CAT(SomePolicy,Base) () {} };                              \
75         typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
76
77     BOOST_PP_SEQ_FOR_EACH( SP_DeclareBase, , BOOST_PP_SEQ_POP_FRONT( SATLIB_SOCKET_POLICIES ) )
78
79 #   undef SP_DeclareBase
80         
81     struct SocketPolicyBase
82     {
83         virtual ~SocketPolicyBase() {}
84
85 #       define SP_DeclareTypedef(x1,x2,SomePolicy)                                              \
86             typedef BOOST_PP_CAT(SomePolicy,Base) SomePolicy;                                   \
87             BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_);         \
88             virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \
89                 { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
90
91         BOOST_PP_SEQ_FOR_EACH( SP_DeclareTypedef, , SATLIB_SOCKET_POLICIES )
92
93 #       undef SP_DeclareTypedef
94     };
95
96 #   define SP_TemplateArgs(x1,x2,n,SomePolicy)                                  \
97         BOOST_PP_COMMA_IF( n )                                                  \
98         class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base)
99
100     template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SATLIB_SOCKET_POLICIES ) >
101     struct SocketPolicy
102         : public SocketPolicyBase
103     {
104 #   define SP_DeclarePolicyMember(x1,x2,SomePolicy)                                     \
105         typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy;                                  \
106         SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_);                        \
107         BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const     \
108             { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
109
110         BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SATLIB_SOCKET_POLICIES )
111 #   undef SP_DeclarePolicyMember
112
113         static void checkBaseOf(SocketPolicyBase const & other);
114     };
115
116 #   undef SP_TemplateArgs
117
118 namespace impl {
119
120     struct nil {};
121
122     template <int N>
123     struct SocketPolicy_rv
124     { int v[N+1]; };
125     
126     template <class Base, class Policy, int N>
127     struct MakeSocketPolicy_merge
128     {};
129
130 #   define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy)            \
131         BOOST_PP_COMMA_IF( m )                                                  \
132         BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy )
133
134 #    define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SATLIB_SOCKET_POLICIES_N ) )
135 #    define BOOST_PP_LOCAL_MACRO(n)                                                                                             \
136         SocketPolicy_rv<n> MakeSocketPolicy_merge_(BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SATLIB_SOCKET_POLICIES ),Base)*);        \
137                                                                                                                                 \
138         template <class Base, class Policy>                                                                                     \
139         struct MakeSocketPolicy_merge<Base,Policy,sizeof(SocketPolicy_rv<n>)>                                                   \
140         {                                                                                                                       \
141             typedef SocketPolicy<                                                                                               \
142                BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, n, SATLIB_SOCKET_POLICIES )                    \
143                > type;                                                                                                          \
144         };
145
146 #   include BOOST_PP_LOCAL_ITERATE()
147
148 #   undef SP_DeclareMakeSocketPolicy_merge_member
149
150     struct MakeSocketPolicy_fold
151     {
152         template <class Base, class Policy>
153         struct apply
154             : MakeSocketPolicy_merge<Base,
155                                      Policy,
156                                      sizeof(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
157         {};
158
159         template <class Base>
160         struct apply<Base,nil>
161         {
162             typedef Base type;
163         };
164     };
165
166     template <class Base, class Vector>
167     struct MakeSocketPolicy_impl
168     {
169         typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy;
170     };
171
172 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)      \
173         BOOST_PP_COMMA_IF( n )                          \
174         typename Base::SomePolicy *
175
176     template <class Base>
177     SocketPolicy_rv<1> SocketPolicy_checkcompat_(
178         BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SATLIB_SOCKET_POLICIES ) );
179
180 #   undef SP_DeclareArguments
181
182     template <class Base>
183     SocketPolicy_rv<2> SocketPolicy_checkcompat_( 
184         BOOST_PP_ENUM_PARAMS( SATLIB_SOCKET_POLICIES_N, void * BOOST_PP_INTERCEPT ) );
185
186     template <int Size>
187     struct SocketPolicy_checkcompat
188         : public boost::false_type
189     {};
190
191     template<>
192     struct SocketPolicy_checkcompat<sizeof(SocketPolicy_rv<1>)>
193         : public boost::true_type
194     {};
195
196
197 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)      \
198         BOOST_PP_COMMA_IF( n )                          \
199         static_cast<typename Derived::SomePolicy *>(0)
200
201     template <class Base, class Derived>
202     struct SocketPolicy_compatibility
203         : public SocketPolicy_checkcompat< sizeof(
204             SocketPolicy_checkcompat_<Base>(
205                 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SATLIB_SOCKET_POLICIES ) )) >
206     {};
207
208 } // namespace impl
209
210     template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SATLIB_SOCKET_POLICIES_N, class T, satcom::lib::impl::nil ) >
211     class MakeSocketPolicy
212         : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
213                                   impl::MakeSocketPolicy_impl< T0, boost::mpl::vector< BOOST_PP_ENUM_SHIFTED_PARAMS( SATLIB_SOCKET_POLICIES_N, T ) > >,
214                                   impl::MakeSocketPolicy_impl< SocketPolicy<>,
215                                                                boost::mpl::vector< BOOST_PP_ENUM_PARAMS( SATLIB_SOCKET_POLICIES_N, T ) > > >::type
216     {};
217
218     template <class BasePolicy, class DerivedPolicy>
219     struct SocketPolicyIsBaseOf
220         : public boost::mpl::if_< boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >,
221                                                     boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >,
222                                   impl::SocketPolicy_compatibility<BasePolicy,DerivedPolicy>,
223                                   boost::false_type >::type
224     {};
225
226 #   define SP_DefineConditions(x1,x2,SomePolicy)                                                \
227         template <class Policy, class Trait>                                                    \
228         struct BOOST_PP_CAT(SomePolicy,Is)                                                      \
229             : public boost::is_convertible< typename Policy::SomePolicy*, Trait* >              \
230         {};                                                                                     \
231                                                                                                 \
232         template <class Policy, class Trait>                                                    \
233         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is)                                     \
234             : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait> >              \
235         {};                                                                                     \
236                                                                                                 \
237         template <class Policy, class Trait>                                                    \
238         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot)                                  \
239             : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait>::value >   \
240         {};
241
242     BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SATLIB_SOCKET_POLICIES )
243
244 #   undef SP_DefineConditions
245
246 }}
247
248 ///////////////////////////////ih.e////////////////////////////////////////
249 #endif
250
251 \f
252 // Local Variables:
253 // mode: c++
254 // c-file-style: "satcom"
255 // End: