Replace all relative includes with abolute ones
[senf.git] / senf / Packets / PacketRegistry.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.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 /** \file
24     \brief PacketRegistry public header */
25
26 #ifndef HH_SENF_Packets_PacketRegistry_
27 #define HH_SENF_Packets_PacketRegistry_ 1
28
29 // Custom includes
30 #include <map>
31 #include <boost/utility.hpp> // for boost::noncopyable
32 #include <boost/optional.hpp>
33 #include <boost/preprocessor/cat.hpp>
34 #include <senf/Utils/Exception.hh>
35 #include "Packet.hh"
36
37 #include "PacketRegistry.ih"
38 //#include "PacketRegistry.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
40
41 namespace senf {
42
43     /** \brief %Packet registration facility
44
45         The %PacketRegistry provides a generic facility to associate an arbitrary key with
46         Packets. Example keys are Ethertype or IP protocols.
47
48         Every %PacketRegistry is identified by a type tag:
49         \code
50         struct SomeTag {
51             typedef some_key_type key_t;
52         };
53         \endcode
54         The key type can be an arbitrary value type. The %PacketRegistry for this Tag can then be
55         accessed using <code>senf::PacketRegistry<SomeTag>::</code>.
56
57         The %PacketRegistry class has only static members and provides access to the packet
58         registry. It allows two-way lookup either by key or by packet type.
59
60         \code
61         senf::Packet::factory_t factory (senf::PacketRegistry<SomeTag>::lookup(some_key).factory());
62         SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
63         \endcode
64
65         Packets can be registered either dynamically or statically. Dynamic:
66         \code
67         // dynamic registration
68         senf::PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
69
70         // static registration. 'registerSomePacket' is an arbitrary symbol name
71         senf::PacketRegistry<SomeTag>::RegistrationProxy<SomePacket>
72             registerSomePacket (key_of_somePacket);
73         \endcode
74
75         This global variable declaration will register \a SomePacket with the \a SomeTag registry
76         under the key \a key_of_somePacket. The variable \a registerSomePacket is a dummy. It's only
77         function is to force the call of it's constructor during global construction time. This
78         static registration only works when the symbol is included into the final binary. To force
79         this inclusion, you should not put packet registrations into a library but into an object
80         file.
81
82         \ingroup packet_module
83      */
84     template <class Tag>
85     class PacketRegistry
86     {
87     public:
88         typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
89
90         /** \brief Statically register a packet type in a PacketRegistry
91
92             To use this class, define a global symbol in the following way:
93             \code
94             namespace {
95                 senf::PacketRegistry<Tag>::RegistrationProxy<PacketType>
96                     registerPacketType (key);
97             }
98             \endcode Here  \a Tag  is the type  tag of the  registry to  register the packet  in, \a
99             PacketType is the packet to register (this  is the ConcretePacket of that packet) and \a
100             key is  the key of  type \c Tag::key_t  under which the packet  is to be  registered. \a
101             registerPacketType is an arbitrary name for the global symbol.
102          */
103         template <class PacketType>
104         struct RegistrationProxy
105         {
106             RegistrationProxy(typename Tag::key_t key);
107         };
108
109         /** \brief Register new packet type
110
111             Register \a PacketType in the packet registry \a Tag under the given \a key.
112
113             \par Preconditions:
114                 The given \a key must be unique and not be assigned to any other
115                 packet class in this registry.  The %Packet must not already be registered in the
116                 registry.
117
118             \tparam PacketType ConcretePacket instantiation of packet to register
119             \param key The key of the packet
120          */
121         template <class PacketType>
122         static void registerPacket(typename Tag::key_t key);
123
124         /** \brief Find key of a packet type
125
126             Return the key of \a PacketType as registered in the \a Tag registry
127
128             \tparam PacketType packet of which the key is requested
129             \returns key of the packet
130             \throws PacketTypeNotRegistered if the packet type is not found in the registry.
131          */
132         template <class PacketType>
133         static typename Tag::key_t key();
134
135         /** \brief Find key of a packet type
136
137             Return the key of \a PacketType as registered in the \a Tag registry
138
139             \tparam PacketType packet of which the key is requested
140             \returns key of the packet wrapped in a <a
141                 href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
142                 an unbound optional, if the key is not found.
143          */
144         template <class PacketType>
145         static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
146
147         /** \brief Find key of a packet
148
149             Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
150
151             \param packet The packet of which the key is requested
152             \returns key of the packet
153             \throws PacketTypeNotRegistered if the packet type is not found in the registry.
154          */
155         static typename Tag::key_t key(Packet const & packet);
156
157         /** \brief Find key of a packet
158
159             Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
160
161             \param packet The packet of which the key is requested
162             \returns key of the packet wrapped in a <a
163                 href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
164                 an unbound optional, if the key is not found.
165          */
166         static typename boost::optional<typename Tag::key_t> key(Packet const & packet, NoThrow_t);
167
168         /** \brief Lookup a packet by it's key
169
170             \throws PacketTypeNotRegistered if the \a key is not found in the registry
171             \return %Packet entry for given \a key
172          */
173         static PkReg_Entry const & lookup(typename Tag::key_t key);
174
175         /** \brief Lookup a packet by it's key
176             \return Pointer to packet entry for given \a key or 0, if the key is not found in the
177                 registry.
178          */
179         static PkReg_Entry const * lookup(typename Tag::key_t key, NoThrow_t);
180
181         /** \brief Beginning iterator to list of registered keys
182          */
183         static iterator begin();
184
185         /** \brief End iterator to list of registered keys
186          */
187         static iterator end();
188
189     private:
190         typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
191         static Registry & registry();
192     };
193
194     /** \brief Statically add an entry to a packet registry
195
196         This macro will declare an anonymous global variable in such a way, that constructing this
197         variable will add a registration to the given packet registry.
198
199         \hideinitializer
200      */
201 #   define SENF_PACKET_REGISTRY_REGISTER( registry, value, type )                                 \
202         namespace {                                                                               \
203             senf::PacketRegistry< registry >::RegistrationProxy< type >                           \
204                 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value );                            \
205         }
206
207     /** \brief Dump all packet registries
208
209         This command will dump all packet registries to the given stream. This is to help debugging
210         registration problems.
211      */
212     void dumpPacketRegistries(std::ostream & os);
213
214     /** \brief Entry not found in registry
215
216         This exception is signaled whenever a throwing lookup operation fails.
217      */
218     struct PacketTypeNotRegisteredException : public senf::Exception
219     { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered"){} };
220
221 }
222
223 ///////////////////////////////hh.e////////////////////////////////////////
224 #endif
225 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
226 #define HH_SENF_Packets_PacketRegistry_i_
227 #include "PacketRegistry.cci"
228 #include "PacketRegistry.ct"
229 #include "PacketRegistry.cti"
230 #endif
231
232
233 // Local Variables:
234 // mode: c++
235 // fill-column: 100
236 // c-file-style: "senf"
237 // indent-tabs-mode: nil
238 // ispell-local-dictionary: "american"
239 // compile-command: "scons -u test"
240 // comment-column: 40
241 // End:
242