From: g0dil Date: Thu, 30 Aug 2007 23:27:30 +0000 (+0000) Subject: Some small documentation fixes X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=21bad90912447cd2d390112cf2d2a7d383ad8058;p=senf.git Some small documentation fixes Utils: Implement mpl.hh metaprogramming helpers git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@418 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Mainpage.dox b/Mainpage.dox index 98afe2b..b0ec91a 100644 --- a/Mainpage.dox +++ b/Mainpage.dox @@ -134,15 +134,21 @@ \see \ref build \n \ref svnsetup + \section libPPI libPPI: Packet Processing Infrastructure + + The Packet Processing Infrastructure implements a modular framework for implementing packet + oriented network applications. The library provides a larget set of pre-defined modules as well + as the necessary helpers to implement application specific processing modules. + + \see libPPI API reference + \section libSocket libSocket: C++ abstraction of the BSD socket API This library provides a high performance and object oriented abstraction of the standard socket API. It utilizes a flexible and extensible policy based design. The library provides predefined - types for the important socket types (UDP and TCP sockets etc) including raw and packet - sockets. \n + types for the important socket types (UDP and TCP sockets etc) including raw and packet sockets. - \see libSocket API - reference + \see libSocket API reference \section libPackets libPackets: Network packet manipulation @@ -150,8 +156,7 @@ packetized network data. Included is a library of several protocol parsers covering the basic IPv4 and IPv6 network protocols down to the Ethernet layer. - \see libPackets API - reference + \see libPackets API reference \section libScheduler libScheduler: Asynchronous event handling diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 9730338..fbaafb6 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -307,9 +307,6 @@ namespace connector { OutputConnector(); }; - ///@{ - ///\addtogroup connectors - /** \brief Combination of PassiveConnector and InputConnector The PassiveInput automatically controls the connectors throttling state using a queueing @@ -392,8 +389,6 @@ namespace connector { void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead }; - ///@} - }}} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/PPI/IOEvent.hh b/PPI/IOEvent.hh index ad239b8..8e18532 100644 --- a/PPI/IOEvent.hh +++ b/PPI/IOEvent.hh @@ -52,6 +52,15 @@ namespace ppi { An IOEvent is signaled, whenever the FileHandle \a handle becomes readable or writable. The type of event is specified using the \a events mask with values from EventFlags. + There are two types of flags: + + \li Event flags (\ref Read, \ref Prio, \ref Write) specify the type of event. The + callback will be called whenever one of the specified events occurs on the filehandle + \li Error flags (\ref Hup, \ref Err) specify some type of error condition on the + filehandle. If you specify an error flag when registering the event, the error condition + will be passed to the callback, otherwise an ErrorException or HangupException will be + thrown. + \see IOEventInfo \ingroup event_group @@ -66,11 +75,13 @@ namespace ppi { // This is stupid, however there is no way to import the Scheduler::EventId enum together // with the enumeration symbols - enum EventFlags { Read = Scheduler::EV_READ, - Prio = Scheduler::EV_PRIO, - Write = Scheduler::EV_WRITE, - Hup = Scheduler::EV_HUP, - Err = Scheduler::EV_ERR }; + enum EventFlags { + Read = Scheduler::EV_READ /**< FileHandle is readable */ + , Prio = Scheduler::EV_PRIO /**< FileHandle priority data is readable */ + , Write = Scheduler::EV_WRITE /**< FileHandle is writable */ + , Hup = Scheduler::EV_HUP /**< Hangup condition on FileHandle */ + , Err = Scheduler::EV_ERR /**< Some other error condition on FileHandle */ + }; /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index f541660..22a0f1b 100644 --- a/Packets/Mainpage.dox +++ b/Packets/Mainpage.dox @@ -57,12 +57,12 @@ udp->source() = 2000u; udp->destination() = 2001u; ip->ttl() = 255u; - ip->source() = senf::INet4Address("192.168.0.1"); // (*) - ip->destination() = senf::INet4Address("192.168.0.2"); // (*) - eth->source() = senf::MACAddress("00:11:22:33:44:55"); - eth->destination() = senf::MACAddress("00:11:22:33:44:66"); + ip->source() = senf::INet4Address::from_string("192.168.0.1"); + ip->destination() = senf::INet4Address::from_string("192.168.0.2"); + eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55"); + eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66"); - eth.finalize(); // (*) + eth.finalize(); \endcode As seen above, packet fields are accessed using the -> operator whereas other packet diff --git a/Packets/PacketParser.cti b/Packets/PacketParser.cti index 777531b..7413037 100644 --- a/Packets/PacketParser.cti +++ b/Packets/PacketParser.cti @@ -77,7 +77,7 @@ prefix_ Parser senf::operator<<(Parser target, Value const & value) template prefix_ senf::PacketParserBase::size_type -senf::detail::packetParserSize(Parser p, int, Parser_TakeNum *) +senf::detail::packetParserSize(Parser p, int, senf::mpl::take_uint *) { return Parser::fixed_bytes; } diff --git a/Packets/PacketParser.ih b/Packets/PacketParser.ih index 9acee0f..2fb098a 100644 --- a/Packets/PacketParser.ih +++ b/Packets/PacketParser.ih @@ -25,6 +25,7 @@ #define IH_PacketParser_ 1 // Custom includes +#include "Utils/mpl.hh" ///////////////////////////////ih.p//////////////////////////////////////// @@ -35,35 +36,41 @@ namespace detail { # ifndef DOXYGEN - template - struct Parser_TakeNum {}; - + // Use SFINAE to check, if Parser has an integer-valued fixed_bytes member. If not, + // 'Parser_TakeNum' fails and the overload is removed from the overload + // set. template PacketParserBase::size_type packetParserSize( - Parser p, int, Parser_TakeNum * = 0); + Parser p, int, senf::mpl::take_uint * = 0); + // An ellipsis is always the worst match. A call 'packetParserSize(p,0) will prefer above + // overload if that is not disabled by SFINAE. template PacketParserBase::size_type packetParserSize(Parser p, ...); - template struct ParserInitBytes_RV { char _[16][n]; }; - + // Same as above: This overload is only enabled, if Parser has an integer values 'init_bytes' + // member. template - ParserInitBytes_RV<1> ParserInitBytes_Choose_(Parser_TakeNum *); - + senf::mpl::rv<0> ParserInitBytes_Choose_(senf::mpl::take_uint *); + template - ParserInitBytes_RV<2> ParserInitBytes_Choose_(...); + senf::mpl::rv<1> ParserInitBytes_Choose_(...); - template + // This version of ParserInitBytes_Choose uses 'Parser::init_bytes' to provide 'value' (via + // 'boost::integral_constant') + template struct ParserInitBytes_Choose : public boost::integral_constant {}; + // If Parser::init_bytes is not defined, this specialization is chosen which instead uses + // 'Parser::fixed_bytes' template - struct ParserInitBytes_Choose)> + struct ParserInitBytes_Choose : public boost::integral_constant {}; template struct ParserInitBytes - : public ParserInitBytes_Choose(0))> {}; + : public ParserInitBytes_Choose(0))> {}; # endif diff --git a/Socket/SocketPolicy.ih b/Socket/SocketPolicy.ih index 6d41c69..0f70243 100644 --- a/Socket/SocketPolicy.ih +++ b/Socket/SocketPolicy.ih @@ -50,6 +50,7 @@ #include #include // for enable_if +#include "Utils/mpl.hh" #include "Utils/pool_alloc_mixin.hh" ///////////////////////////////ih.p//////////////////////////////////////// @@ -112,11 +113,7 @@ namespace impl { struct nil {}; - template - struct SocketPolicy_rv - { int v[N+1]; }; - - template + template struct MakeSocketPolicy_merge {}; @@ -126,11 +123,11 @@ namespace impl { # define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) ) # define BOOST_PP_LOCAL_MACRO(n) \ - SocketPolicy_rv MakeSocketPolicy_merge_( \ + senf::mpl::rv MakeSocketPolicy_merge_( \ BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*); \ \ template \ - struct MakeSocketPolicy_merge)> \ + struct MakeSocketPolicy_merge \ { \ typedef SocketPolicy< \ BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, \ @@ -149,7 +146,7 @@ namespace impl { struct apply : MakeSocketPolicy_merge(0)))> + SENF_MPL_RV(MakeSocketPolicy_merge_(static_cast(0)))> {}; template @@ -170,13 +167,13 @@ namespace impl { typename Base::SomePolicy * template - SocketPolicy_rv<1> SocketPolicy_checkcompat_( + senf::mpl::rv<1> SocketPolicy_checkcompat_( BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) ); # undef SP_DeclareArguments template - SocketPolicy_rv<2> SocketPolicy_checkcompat_( ... ); + senf::mpl::rv<2> SocketPolicy_checkcompat_( ... ); template struct SocketPolicy_checkcompat @@ -184,7 +181,7 @@ namespace impl { {}; template<> - struct SocketPolicy_checkcompat)> + struct SocketPolicy_checkcompat<1> : public boost::true_type {}; @@ -195,7 +192,7 @@ namespace impl { template struct SocketPolicy_compatibility - : public SocketPolicy_checkcompat< sizeof( + : public SocketPolicy_checkcompat< SENF_MPL_RV( SocketPolicy_checkcompat_( BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) > {}; diff --git a/Utils/Mainpage.dox b/Utils/Mainpage.dox index b0670e6..822c40b 100644 --- a/Utils/Mainpage.dox +++ b/Utils/Mainpage.dox @@ -10,8 +10,6 @@ namespace senf {
SystemException
standard exception for system errors (errno)
-
\ref time
Very rudimentary microsecond time support
-
\ref process
Some simple process management and daemon helpers
\ref membind
a simple \ref TypeIdValue
class wrapping a typeid in a way that it can be used like any other value type, e.g. as the key in a map.
-
\ref hexdump
-
a simple but usefull function to write binary data in in hexadecimal format.
+
\ref hexdump
a simple but usefull function to write binary data in in hexadecimal + format.
+ +
\ref senfmpl
Some simple tools which help to solve common meta-programming + tasks
*/ diff --git a/Utils/mpl.hh b/Utils/mpl.hh new file mode 100644 index 0000000..2983ffe --- /dev/null +++ b/Utils/mpl.hh @@ -0,0 +1,221 @@ +// $Id$ +// +// Copyright (C) 2007 +// 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. + +/** \file + \brief mpl public header */ + +#ifndef HH_mpl_ +#define HH_mpl_ 1 + +// Custom includes + +//#include "mpl.mpp" +#include "mpl.ih" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace mpl { + + /** \defgroup senfmpl Low-level template meta programming helpers + */ + +# ifndef SENF_MPL_RV_ALIGNMENT +# define SENF_MPL_RV_ALIGNMENT 16 +# endif + + /** \brief Return-value type used to implement overload selection + + The senf::mpl::rv type is used together with \ref SENF_MPL_RV() to select template + specializations based on a set of overloads: + + \code + template struct select {}; + + // Case 0 + template <> + struct select<0> { + static bool const has_int_value = true; + void frobble(); + }; + template + senf::mpl::rv<0> select_(int, senf::mpl::take_int * = 0); + + // Case 1 + template <> + struct select<1> { + static bool const has_int_value = false; + void dazzle(); + }; + template + senf::mpl::rv<1> select_(...); + + template + struct choice : public select(0) )> {}; + + struct A { static const int value = 0; }; + struct B {}; + + choice
a; a.frobble(); + choice b; b.dazzle(); + \endcode + + The selection is always based on two components: A selector class specialized for each of + the possible choices and an overloaded function (only signatures, no implementation needed) + to provide the conditions. + + When instantiatinv choice, we forward \a T to the select_ set of + overloads. Because of SFINAE, the overload + set will only contain those instantiations, for which template expansion does not fail. + + So, if \a T has an integer \c value member, both \c select_ overloads are ok and the call + select_(0) will choose the first (case 0) variant, since the argument \c 0 is + better matched by \c int than by .... + + However, if \a T does not have an integer \c value member, expansion for the first overload + fails and the overload set only contains the second case. + + \ref SENF_MPL_RV() internally uses \c sizeof to find out, \e which overload was selected + and returns the senf::mpl::rv-argument of that overloads return type. For this to work, the + \c select_ functions need not be implemented since no code is generated and \c select_ is + never called. + + This number is than forwarded as template argument to \c select which is specialized for + each case. Therefore, choice has a \c frobble() member whereas + choice has a \c dazzle() member. + + \see \ref SENF_MPL_RV + \ingroup senfmpl + */ + template + struct rv { + char _[SENF_MPL_RV_ALIGNMENT][n+1]; + }; + + /** \brief Get return value of overload selector + + Used together with senf::mpl::rv to implement overload selection. + + \see \ref senf::mpl::rv + \ingroup senfmpl + \hideinitializer + */ +# define SENF_MPL_RV(expr) (sizeof(expr)/SENF_MPL_RV_ALIGNMENT-1) + + /** \brief Take an arbitrary unsigned integer template argument + + Used together with SFINAE: The expression + take_uint< \a expr > is only valid if \a expr is valid and returns a value + convertible to an unsigned integer. + + \ingroup senfmpl + */ + template struct take_uint {}; + + /** \brief Take an arbitrary integer template argument + + Used together with SFINAE: The expression + take_int< \a expr > is only valid if \a expr is valid and returns a value + convertible to an integer. + + \ingroup senfmpl + */ + template struct take_int {}; + + /** \brief Take an arbitrary type template argument + + Used together with SFINAE: The expression + take_class< \a expr > is only valid if \a expr is valid and is a type. + + \ingroup senfmpl + */ + template struct take_class {}; + + /** \brief Define 'previous value' slot + + The 'previous value' macros \ref SENF_MPL_PREVV_DEF(), \ref SENF_MPL_PREVV_SET() and \ref + SENF_MPL_PREVV_GET() provide a facility to get the last unsigned integer value assigned to + the slot before the current point in the current class. + \code + struct Foo + { + // Define PREVV slot named 'accum' initialized to 0 + SENF_MPL_PREVV_DEF(accum, 0); + + // Add 2 to 'accum' + SENF_MPL_PREVV_SET(accum, SENF_MPL_PREVV_GET(accum) + 2); + + // Multiply 'accum' by 3 + SENF_MPL_PREVV_SET(accum, SENF_MPL_PREVV_GET(accum) * 3); + + // Define the result as a constant expression. result is now 6 + static unsigned result = SENF_MPL_PREVV_GET(accum); + }; + \endcode + Of course, it does not make sense to use these macros for simple arithmetic as in the + example. The SENF_MPL_PREVV macros allow to define macros which pass information from one + macro invocation to the next. + + \implementation The implementation is based on __LINE__: We check backwards for a value + defined on a previous line. The check is limited to 80 lines backwards. + + \ingroup senfmpl + \hideinitializer + */ +# define SENF_MPL_PREVV_DEF(name,value) \ + template \ + static senf::mpl::rv<0> _SENF_MPL_PREVV_ ## name (senf::mpl::rv<_> *); \ + SENF_MPL_PREVV_SET(name,value) + + /** \brief Set 'prevision value' slot + \see \ref SENF_MPL_PREVV_DEF() + \ingroup senfmpl + \hideinitializer + */ +# define SENF_MPL_PREVV_SET(name,value) \ + static senf::mpl::rv _SENF_MPL_PREVV_ ## name (senf::mpl::rv<__LINE__>*) + + /** \brief Get current 'previous value' slot value + \see \ref SENF_MPL_PREVV_DEF() + \ingroup senfmpl + \hideinitializer + */ +# define SENF_MPL_PREVV_GET(name) \ + SENF_MPL_PREVV_I_GET(name) + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "mpl.cci" +//#include "mpl.ct" +//#include "mpl.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/mpl.test.cc b/Utils/mpl.test.cc new file mode 100644 index 0000000..9935670 --- /dev/null +++ b/Utils/mpl.test.cc @@ -0,0 +1,97 @@ +// $Id$ +// +// Copyright (C) 2007 +// 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. + +/** \file + \brief mpl.test unit tests */ + +//#include "mpl.test.hh" +//#include "mpl.test.ih" + +// Custom includes +#include "mpl.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + template + struct select { + static bool const has_int_value = false; + static bool const has_class_value = false; + }; + template + senf::mpl::rv<0> select_(...); + + + template <> + struct select<1> { + static bool const has_int_value = true; + static bool const has_class_value = false; + }; + template + senf::mpl::rv<1> select_(int, senf::mpl::take_int * = 0); + + template <> + struct select<2> { + static bool const has_int_value = false; + static bool const has_class_value = true; + }; + template + senf::mpl::rv<2> select_(int, senf::mpl::take_class * = 0); + + template + struct choice : public select(0) )> {}; + + struct A { static const int value = 0; }; + struct B { struct value {}; }; + struct C {}; +} + +BOOST_AUTO_UNIT_TEST(senfmpl) +{ + BOOST_CHECK( choice::has_int_value ); + BOOST_CHECK( ! choice::has_class_value ); + + BOOST_CHECK( ! choice::has_int_value ); + BOOST_CHECK( choice::has_class_value ); + + BOOST_CHECK( ! choice::has_int_value ); + BOOST_CHECK( ! choice::has_class_value ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: