// $Id$
//
// Copyright (C) 2006
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-// Stefan Bund <stefan.bund@fokus.fraunhofer.de>
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// 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
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+/** \file
+ \brief PacketRegistry public header */
-#ifndef HH_PacketRegistryImpl_
-#define HH_PacketRegistryImpl_ 1
+#ifndef HH_SENF_Packets_PacketRegistry_
+#define HH_SENF_Packets_PacketRegistry_ 1
// Custom includes
#include <map>
#include <boost/utility.hpp> // for boost::noncopyable
-#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include "../Utils/Exception.hh"
#include "Packet.hh"
+#include "PacketRegistry.ih"
//#include "PacketRegistry.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
- namespace impl { template <class key> class PacketRegistryImpl; }
-
/** \brief Packet registration facility
- The PacketRegistry provides a generic facility to associate an
- arbitrary key with Packets. Example keys are Ethertype or IP
- protocols.
+ The PacketRegistry provides a generic facility to associate an arbitrary key with
+ Packets. Example keys are Ethertype or IP protocols.
Every PacketRegistry is identified by a type tag:
\code
- struct SomeTag {
- typedef some_key_type key_t;
- };
+ struct SomeTag {
+ typedef some_key_type key_t;
+ };
\endcode
- The key type can be an arbitrary valuetype. The PacketRegistry
- for this Tag can then be accessed using
- <code>PacketRegistry<SomeTag>::</code>.
+ The key type can be an arbitrary value type. The PacketRegistry for this Tag can then be
+ accessed using <code>senf::PacketRegistry<SomeTag>::</code>.
- The PacketRegistry class has only static members and provides
- access to the packet registry. It allows to register Packet
- classes and to create new Packets given a key. Methods are
- also provided to find the key of a Packet type.
+ The PacketRegistry class has only static members and provides access to the packet
+ registry. It allows two-way lookup either by key or by packet type.
\code
- PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
- p = PacketRegistry<SomeTag>::create(some_key,begin,end);
- SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
+ senf::Packet::factory_t factory (senf::PacketRegistry<SomeTag>::lookup(some_key).factory());
+ SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
\endcode
- Normally, packet classes are registered statically and not
- procedurally. To this end, the RegistrationProxy is provided:
+ Packets can be registered either dynamically or statically. Dynamic:
\code
- PacketRegistry<SomeTag>::RegistrationProxy<SomePacket>
- registerSomePacket (key_of_somePacket);
+ // dynamic registration
+ senf::PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
+
+ // static registration. 'registerSomePacket' is an arbitrary symbol name
+ senf::PacketRegistry<SomeTag>::RegistrationProxy<SomePacket>
+ registerSomePacket (key_of_somePacket);
\endcode
- This global variable declaration will register \c SomePacket
- with the \c SomeTag registry under the key \c
- key_of_somePacket. The variable \c registerSomePacket is a
- dummy. It's only function is to force the call of it's
- constructor during global construction time.
-
- The PacketRegistry's purpose is mostly to assist in
- implementing the v_nextInterpreter() member of packet
- facades. This is further supported by the PacketRegistryMixin
- class.
-
- \todo Add parameterless create() method
+
+ This global variable declaration will register \a SomePacket with the \a SomeTag registry
+ under the key \a key_of_somePacket. The variable \a registerSomePacket is a dummy. It's only
+ function is to force the call of it's constructor during global construction time. This
+ static registration only works when the symbol is included into the final binary. To force
+ this inclusion, you should not put packet registrations into a library but into an object
+ file.
+
+ \ingroup packet_module
*/
template <class Tag>
class PacketRegistry
{
public:
+ typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
+
/** \brief Statically register a packet type in a PacketRegistry
- \fixme This fails to work within a library since the linker will
- remove all unused object files ...
+ To use this class, define a global symbol in the following way:
+ \code
+ namespace {
+ senf::PacketRegistry<Tag>::RegistrationProxy<PacketType>
+ registerPacketType (key);
+ }
+ \endcode Here \a Tag is the type tag of the registry to register the packet in, \a
+ PacketType is the packet to register (this is the ConcretePacket of that packet) and \a
+ key is the key of type \c Tag::key_t under which the packet is to be registered. \a
+ registerPacketType is an arbitrary name for the global symbol.
*/
- template <class OtherPacket>
+ template <class PacketType>
struct RegistrationProxy
{
RegistrationProxy(typename Tag::key_t key);
/** \brief Register new packet type
- Register \c OtherPacket in the packet registry \c Tag
- under the given \c key.
+ Register \a PacketType in the packet registry \a Tag under the given \a key.
- \par Preconditions:
- The given \c key must be unique and not be assigned to
- any other packet class in this registry.
- The Packet must not already be registered in the registry.
+ \par Preconditions: The given \a key must be unique and not be assigned to any other
+ packet class in this registry. The Packet must not already be registered in the
+ registry.
- \param OtherPacket packet to regiser
- \param key key of the packet
+ \param PacketType ConcretePacket instantiation of packet to register
+ \param key The key of the packet
*/
- template <class OtherPacket>
+ template <class PacketType>
static void registerPacket(typename Tag::key_t key);
- /** \brief Find key of a packet
+ /** \brief Find key of a packet type
- Return the key of \c OtherPacket as registered in the \c
- Tag registry
+ Return the key of \a PacketType as registered in the \a Tag registry
- \param OtherPacket packet of which the key is requested
+ \param PacketType packet of which the key is requested
\returns key of the packet
- \throws PacketTypeNotRegistered if the packet type is not
- found in the registry.
+ \throws PacketTypeNotRegistered if the packet type is not found in the registry.
*/
- template <class OtherPacket>
+ template <class PacketType>
static typename Tag::key_t key();
- /** \brief Create new Packet
+ /** \brief Find key of a packet type
+
+ Return the key of \a PacketType as registered in the \a Tag registry
+
+ \param PacketType packet of which the key is requested
+ \returns key of the packet wrapped in a <a
+ href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
+ an unbound optional, if the key is not found.
+ */
+ template <class PacketType>
+ static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
+
+ /** \brief Find key of a packet
+
+ Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
+
+ \param packet The packet of which the key is requested
+ \returns key of the packet
+ \throws PacketTypeNotRegistered if the packet type is not found in the registry.
+ */
+ static typename Tag::key_t key(Packet packet);
+
+ /** \brief Find key of a packet
+
+ Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
+
+ \param packet The
+packet of which the key is requested
+ \returns key of the packet wrapped in a <a
+ href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
+ an unbound optional, if the key is not found.
+ */
+ static typename boost::optional<typename Tag::key_t> key(Packet packet, NoThrow_t);
+
+ /** \brief Lookup a packet by it's key
+
+ \throws PacketTypeNotRegistered if the \a key is not found in the registry
+ \return Packet entry for given \a key
+ */
+ static PkReg_Entry const & lookup(typename Tag::key_t key);
+
+ /** \brief Lookup a packet by it's key
+ \return Pointer to packet entry for given \a key or 0, if the key is not found in the
+ registry.
+ */
+ static PkReg_Entry const * lookup(typename Tag::key_t key, NoThrow_t);
- \param key Key of packet type to create instance of
- \param b begin iterator argument to Packet::create()
- \param e end iterator argment to Packet::create()
- \returns new Instance of the packet type registered under
- key or DataPacket, if the key is not registered.
+ /** \brief Beginning iterator to list of registered keys
*/
- template <class InputIterator>
- static Packet::ptr create(typename Tag::key_t key, InputIterator b, InputIterator e);
+ static iterator begin();
+
+ /** \brief End iterator to list of registered keys
+ */
+ static iterator end();
private:
- typedef impl::PacketRegistryImpl<typename Tag::key_t> Registry;
+ typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
static Registry & registry();
-
- template <class T, class D> friend class PacketRegistryMixin;
};
- /** \brief Helper class for v_nextInterpreter implementations
+ /** \brief Statically add an entry to a packet registry
- This class is a helper class which is to be inherited from in
- a packet facade which wants to register a new interpreter with
- the packet framework depending on a packet registry.
+ This macro will declare an anonymous global variable in such a way, that constructing this
+ variable will add a registration to the given packet registry.
- This mixin class provides a new registerInterpreter
- implementation which can be used besides the methods provided
- bei senf::Packet to add a new interpreter to the
- interpreter chain.
+ \hideinitializer
+ */
+# define SENF_PACKET_REGISTRY_REGISTER( registry, value, type ) \
+ namespace { \
+ senf::PacketRegistry< registry >::RegistrationProxy< type > \
+ BOOST_PP_CAT(packetRegistration_, __LINE__) ( value ); \
+ }
- \code
- class SomePacket
- : public Packet,
- private PacketRegistryMixin<SomeTag,SomePacket>
- {
- using Packet::retgisterInterpreter;
- using PacketRegistryMixin<SomeTag,SomePacket>::registerInterpreter;
-
- virtual void v_nextInterpreter()
- {
- registerInterpreter(some_key_value, subpacket_begin, subpacket_end);
- }
- };
- \endcode
- This example is not complete, it only contains the parts
- concerned with PacketRegistryMixin.
+ /** \brief Dump all packet registries
+
+ This command will dump all packet registries to the given stream. This is to help debugging
+ registration problems.
*/
- template <class Tag, class Derived>
- class PacketRegistryMixin
- {
- protected:
- /** \brief add interpreter to interpreter chain
-
- This method is used by v_nextInterpreter() to add a new
- interpreter to the interpreter chain (see the Packet
- reference for more). Instead of specifying the type of
- packet to use as a template argument it is specified using
- the \c key value from the \c Tag registry
- */
- void registerInterpreter(typename Tag::key_t key,
- Packet::iterator b, Packet::iterator e) const;
- };
+ void dumpPacketRegistries(std::ostream & os);
- struct PacketTypeNotRegistered : public std::exception
- { virtual char const * what() const throw() { return "packet type not registered"; } };
+ /** \brief Entry not found in registry
+
+ This exception is signaled whenever a throwing lookup operation fails.
+ */
+ struct PacketTypeNotRegisteredException : public senf::Exception
+ { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered"){} };
}
///////////////////////////////hh.e////////////////////////////////////////
-//#include "PacketRegistry.cci"
+#endif
+#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
+#define HH_SENF_Packets_PacketRegistry_i_
+#include "PacketRegistry.cci"
#include "PacketRegistry.ct"
#include "PacketRegistry.cti"
#endif
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
// End:
+