// $Id$ // // Copyright (C) 2006 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) // Kompetenzzentrum fuer Satelitenkommunikation (SatCom) // Stefan Bund // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef IH_SocketPolicy_ #define IH_SocketPolicy_ 1 // Custom includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for enable_if #include "GenericSockAddr.hh" ///////////////////////////////ih.p//////////////////////////////////////// namespace senf { # define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES ) // This REALLY is bad ... but we just need an Address member in // AddressingPolicyBase as long as ClientSocketHandle / // ServerSocketHandle don't make use of enable_if for each and // every member they define ... struct AddressingPolicyBase { virtual ~ AddressingPolicyBase() {} typedef GenericSockAddr Address; }; # define SP_DeclareBase(x1,x2,SomePolicy) \ struct BOOST_PP_CAT(SomePolicy,Base) \ { virtual ~ BOOST_PP_CAT(SomePolicy,Base) () {} }; \ typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy); BOOST_PP_SEQ_FOR_EACH( SP_DeclareBase, , BOOST_PP_SEQ_POP_FRONT( SENF_SOCKET_POLICIES ) ) # undef SP_DeclareBase struct SocketPolicyBase { virtual ~SocketPolicyBase() {} # define SP_DeclareTypedef(x1,x2,SomePolicy) \ typedef BOOST_PP_CAT(SomePolicy,Base) SomePolicy; \ BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); \ virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \ { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); } BOOST_PP_SEQ_FOR_EACH( SP_DeclareTypedef, , SENF_SOCKET_POLICIES ) # undef SP_DeclareTypedef }; # define SP_TemplateArgs(x1,x2,n,SomePolicy) \ BOOST_PP_COMMA_IF( n ) \ class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base) template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) > struct SocketPolicy : public SocketPolicyBase { # define SP_DeclarePolicyMember(x1,x2,SomePolicy) \ typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy; \ SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); \ BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \ { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); } BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES ) # undef SP_DeclarePolicyMember static void checkBaseOf(SocketPolicyBase const & other); }; # undef SP_TemplateArgs namespace impl { struct nil {}; template struct SocketPolicy_rv { int v[N+1]; }; template struct MakeSocketPolicy_merge {}; # define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy) \ BOOST_PP_COMMA_IF( m ) \ BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy ) # define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) ) # define BOOST_PP_LOCAL_MACRO(n) \ SocketPolicy_rv MakeSocketPolicy_merge_(BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*); \ \ template \ struct MakeSocketPolicy_merge)> \ { \ typedef SocketPolicy< \ BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, n, SENF_SOCKET_POLICIES ) \ > type; \ }; # include BOOST_PP_LOCAL_ITERATE() # undef SP_DeclareMakeSocketPolicy_merge_member struct MakeSocketPolicy_fold { template struct apply : MakeSocketPolicy_merge(0)))> {}; template struct apply { typedef Base type; }; }; template struct MakeSocketPolicy_impl { typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy; }; # define SP_DeclareArguments(x1,x2,n,SomePolicy) \ BOOST_PP_COMMA_IF( n ) \ typename Base::SomePolicy * template SocketPolicy_rv<1> SocketPolicy_checkcompat_( BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) ); # undef SP_DeclareArguments template SocketPolicy_rv<2> SocketPolicy_checkcompat_( BOOST_PP_ENUM_PARAMS( SENF_SOCKET_POLICIES_N, void * BOOST_PP_INTERCEPT ) ); template struct SocketPolicy_checkcompat : public boost::false_type {}; template<> struct SocketPolicy_checkcompat)> : public boost::true_type {}; # define SP_DeclareArguments(x1,x2,n,SomePolicy) \ BOOST_PP_COMMA_IF( n ) \ static_cast(0) template struct SocketPolicy_compatibility : public SocketPolicy_checkcompat< sizeof( SocketPolicy_checkcompat_( BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) > {}; } // namespace impl template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N, class T, senf::impl::nil ) > class MakeSocketPolicy : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >, impl::MakeSocketPolicy_impl< T0, boost::mpl::vector< BOOST_PP_ENUM_SHIFTED_PARAMS( SENF_SOCKET_POLICIES_N, T ) > >, impl::MakeSocketPolicy_impl< SocketPolicy<>, boost::mpl::vector< BOOST_PP_ENUM_PARAMS( SENF_SOCKET_POLICIES_N, T ) > > >::type {}; template struct SocketPolicyIsBaseOf : public boost::mpl::if_< boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >, boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >, impl::SocketPolicy_compatibility, boost::false_type >::type {}; # define SP_DefineConditions(x1,x2,SomePolicy) \ template \ struct BOOST_PP_CAT(SomePolicy,Is) \ : public boost::is_convertible< typename Policy::SomePolicy*, Trait* > \ {}; \ \ template \ struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is) \ : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is) > \ {}; \ \ template \ struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot) \ : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)::value > \ {}; BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES ) # undef SP_DefineConditions } ///////////////////////////////ih.e//////////////////////////////////////// #endif // Local Variables: // mode: c++ // c-file-style: "senf" // End: