\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 <a href="../../PPI/doc/html/index.html">libPPI API reference</a>
+
\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 <a href="../../Socket/doc/html/index.html">libSocket API
- reference</a>
+ \see <a href="../../Socket/doc/html/index.html">libSocket API reference</a>
\section libPackets libPackets: Network packet manipulation
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 <a href="../../Packets/doc/html/index.html">libPackets API
- reference</a>
+ \see <a href="../../Packets/doc/html/index.html">libPackets API reference</a>
\section libScheduler libScheduler: Asynchronous event handling
OutputConnector();
};
- ///@{
- ///\addtogroup connectors
-
/** \brief Combination of PassiveConnector and InputConnector
The PassiveInput automatically controls the connectors throttling state using a queueing
void connect(PassiveInput & target); ///< Internal: Use senf::ppi::connect() instead
};
- ///@}
-
}}}
///////////////////////////////hh.e////////////////////////////////////////
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 <em>Event flags</em> (\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 <em>Error flags</em> (\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
// 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
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 <tt>-></tt> operator whereas other packet
template <class Parser>
prefix_ senf::PacketParserBase::size_type
-senf::detail::packetParserSize(Parser p, int, Parser_TakeNum<Parser::fixed_bytes> *)
+senf::detail::packetParserSize(Parser p, int, senf::mpl::take_uint<Parser::fixed_bytes> *)
{
return Parser::fixed_bytes;
}
#define IH_PacketParser_ 1
// Custom includes
+#include "Utils/mpl.hh"
///////////////////////////////ih.p////////////////////////////////////////
# ifndef DOXYGEN
- template <PacketParserBase::size_type i>
- struct Parser_TakeNum {};
-
+ // Use SFINAE to check, if Parser has an integer-valued fixed_bytes member. If not,
+ // 'Parser_TakeNum<Parser::fixed_bytes>' fails and the overload is removed from the overload
+ // set.
template <class Parser>
PacketParserBase::size_type packetParserSize(
- Parser p, int, Parser_TakeNum<Parser::fixed_bytes> * = 0);
+ Parser p, int, senf::mpl::take_uint<Parser::fixed_bytes> * = 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 <class Parser>
PacketParserBase::size_type packetParserSize(Parser p, ...);
- template <unsigned n> struct ParserInitBytes_RV { char _[16][n]; };
-
+ // Same as above: This overload is only enabled, if Parser has an integer values 'init_bytes'
+ // member.
template <class Parser>
- ParserInitBytes_RV<1> ParserInitBytes_Choose_(Parser_TakeNum<Parser::init_bytes> *);
-
+ senf::mpl::rv<0> ParserInitBytes_Choose_(senf::mpl::take_uint<Parser::init_bytes> *);
+
template <class Parser>
- ParserInitBytes_RV<2> ParserInitBytes_Choose_(...);
+ senf::mpl::rv<1> ParserInitBytes_Choose_(...);
- template <class Parser, unsigned size>
+ // This version of ParserInitBytes_Choose uses 'Parser::init_bytes' to provide 'value' (via
+ // 'boost::integral_constant')
+ template <class Parser, unsigned _>
struct ParserInitBytes_Choose
: public boost::integral_constant<PacketParserBase::size_type, Parser::init_bytes> {};
+ // If Parser::init_bytes is not defined, this specialization is chosen which instead uses
+ // 'Parser::fixed_bytes'
template <class Parser>
- struct ParserInitBytes_Choose<Parser, sizeof(ParserInitBytes_RV<2>)>
+ struct ParserInitBytes_Choose<Parser, 1>
: public boost::integral_constant<PacketParserBase::size_type, Parser::fixed_bytes> {};
template <class Parser>
struct ParserInitBytes
- : public ParserInitBytes_Choose<Parser, sizeof(ParserInitBytes_Choose_<Parser>(0))> {};
+ : public ParserInitBytes_Choose<Parser,SENF_MPL_RV(ParserInitBytes_Choose_<Parser>(0))> {};
# endif
#include <boost/mpl/and.hpp>
#include <boost/utility.hpp> // for enable_if
+#include "Utils/mpl.hh"
#include "Utils/pool_alloc_mixin.hh"
///////////////////////////////ih.p////////////////////////////////////////
struct nil {};
- template <int N>
- struct SocketPolicy_rv
- { int v[N+1]; };
-
- template <class Base, class Policy, int N>
+ template <class Base, class Policy, int _>
struct MakeSocketPolicy_merge
{};
# define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) )
# define BOOST_PP_LOCAL_MACRO(n) \
- SocketPolicy_rv<n> MakeSocketPolicy_merge_( \
+ senf::mpl::rv<n> MakeSocketPolicy_merge_( \
BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*); \
\
template <class Base, class Policy> \
- struct MakeSocketPolicy_merge<Base,Policy,sizeof(SocketPolicy_rv<n>)> \
+ struct MakeSocketPolicy_merge<Base,Policy,n> \
{ \
typedef SocketPolicy< \
BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, \
struct apply
: MakeSocketPolicy_merge<Base,
Policy,
- sizeof(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
+ SENF_MPL_RV(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
{};
template <class Base>
typename Base::SomePolicy *
template <class Base>
- 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 <class Base>
- SocketPolicy_rv<2> SocketPolicy_checkcompat_( ... );
+ senf::mpl::rv<2> SocketPolicy_checkcompat_( ... );
template <int Size>
struct SocketPolicy_checkcompat
{};
template<>
- struct SocketPolicy_checkcompat<sizeof(SocketPolicy_rv<1>)>
+ struct SocketPolicy_checkcompat<1>
: public boost::true_type
{};
template <class Base, class Derived>
struct SocketPolicy_compatibility
- : public SocketPolicy_checkcompat< sizeof(
+ : public SocketPolicy_checkcompat< SENF_MPL_RV(
SocketPolicy_checkcompat_<Base>(
BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) >
{};
<dt>SystemException</dt><dd>standard exception for system errors (errno)</dd>
- <dt>\ref time</dt><dd>Very rudimentary microsecond time support</dd>
-
<dt>\ref process</dt><dd>Some simple process management and daemon helpers<?dd>
<dt>\ref membind</dt><dd>a simple <a
<dt>\ref TypeIdValue</dt><dd>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.</dd>
- <dt>\ref hexdump<dt>
- <dd>a simple but usefull function to write binary data in in hexadecimal format.</dd>
+ <dt>\ref hexdump<dt><dd>a simple but usefull function to write binary data in in hexadecimal
+ format.</dd>
+
+ <dt>\ref senfmpl</dt><dd>Some simple tools which help to solve common meta-programming
+ tasks</dd>
</dl>
*/
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <unsigned _> struct select {};
+
+ // Case 0
+ template <>
+ struct select<0> {
+ static bool const has_int_value = true;
+ void frobble();
+ };
+ template <class T>
+ senf::mpl::rv<0> select_(int, senf::mpl::take_int<T::value> * = 0);
+
+ // Case 1
+ template <>
+ struct select<1> {
+ static bool const has_int_value = false;
+ void dazzle();
+ };
+ template <class T>
+ senf::mpl::rv<1> select_(...);
+
+ template <class T>
+ struct choice : public select<SENF_MPL_RV( select_<T>(0) )> {};
+
+ struct A { static const int value = 0; };
+ struct B {};
+
+ choice<A> a; a.frobble();
+ choice<B> 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 <tt>choice<T></tt>, we forward \a T to the <tt>select_</tt> set of
+ overloads. Because of <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>, 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
+ <tt>select_<T>(0)</tt> will choose the first (case 0) variant, since the argument \c 0 is
+ better matched by \c int than by <tt>...</tt>.
+
+ 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, <tt>choice<A></tt> has a \c frobble() member whereas
+ <tt>choice<B></tt> has a \c dazzle() member.
+
+ \see \ref SENF_MPL_RV
+ \ingroup senfmpl
+ */
+ template <unsigned n>
+ 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 <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
+ <tt>take_uint<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
+ convertible to an unsigned integer.
+
+ \ingroup senfmpl
+ */
+ template <unsigned long _> struct take_uint {};
+
+ /** \brief Take an arbitrary integer template argument
+
+ Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
+ <tt>take_int<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
+ convertible to an integer.
+
+ \ingroup senfmpl
+ */
+ template <long _> struct take_int {};
+
+ /** \brief Take an arbitrary type template argument
+
+ Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
+ <tt>take_class<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and is a type.
+
+ \ingroup senfmpl
+ */
+ template <class _> 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 <unsigned _> \
+ 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<unsigned(value)+1> _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
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+ template <unsigned _>
+ struct select {
+ static bool const has_int_value = false;
+ static bool const has_class_value = false;
+ };
+ template <class T>
+ senf::mpl::rv<0> select_(...);
+
+
+ template <>
+ struct select<1> {
+ static bool const has_int_value = true;
+ static bool const has_class_value = false;
+ };
+ template <class T>
+ senf::mpl::rv<1> select_(int, senf::mpl::take_int<T::value> * = 0);
+
+ template <>
+ struct select<2> {
+ static bool const has_int_value = false;
+ static bool const has_class_value = true;
+ };
+ template <class T>
+ senf::mpl::rv<2> select_(int, senf::mpl::take_class<typename T::value> * = 0);
+
+ template <class T>
+ struct choice : public select<SENF_MPL_RV( select_<T>(0) )> {};
+
+ struct A { static const int value = 0; };
+ struct B { struct value {}; };
+ struct C {};
+}
+
+BOOST_AUTO_UNIT_TEST(senfmpl)
+{
+ BOOST_CHECK( choice<A>::has_int_value );
+ BOOST_CHECK( ! choice<A>::has_class_value );
+
+ BOOST_CHECK( ! choice<B>::has_int_value );
+ BOOST_CHECK( choice<B>::has_class_value );
+
+ BOOST_CHECK( ! choice<C>::has_int_value );
+ BOOST_CHECK( ! choice<C>::has_class_value );
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// 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: