added FormFeed character for emacs to end of files
[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         To simplify static registration the SENF_PACKET_REGISTRY_REGISTER macro can be used:
83         \code
84         SENF_PACKET_REGISTRY_REGISTER(SomeTag, SomePacket, key_of_somePacket);
85         \endcode
86
87         \ingroup packet_module
88      */
89     template <class Tag>
90     class PacketRegistry
91     {
92     public:
93         typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
94
95         /** \brief Statically register a packet type in a PacketRegistry
96
97             To use this class, define a global symbol in the following way:
98             \code
99             namespace {
100                 senf::PacketRegistry<Tag>::RegistrationProxy<PacketType>
101                     registerPacketType (key);
102             }
103             \endcode Here  \a Tag  is the type  tag of the  registry to  register the packet  in, \a
104             PacketType is the packet to register (this  is the ConcretePacket of that packet) and \a
105             key is  the key of  type \c Tag::key_t  under which the packet  is to be  registered. \a
106             registerPacketType is an arbitrary name for the global symbol.
107          */
108         template <class PacketType>
109         struct RegistrationProxy
110         {
111             RegistrationProxy(typename Tag::key_t key);
112         };
113
114         /** \brief Register new packet type
115
116             Register \a PacketType in the packet registry \a Tag under the given \a key.
117
118             \par Preconditions:
119                 The given \a key must be unique and not be assigned to any other
120                 packet class in this registry.  The %Packet must not already be registered in the
121                 registry.
122
123             \tparam PacketType ConcretePacket instantiation of packet to register
124             \param key The key of the packet
125          */
126         template <class PacketType>
127         static void registerPacket(typename Tag::key_t key);
128
129         /** \brief Find key of a packet type
130
131             Return the key of \a PacketType as registered in the \a Tag registry
132
133             \tparam PacketType packet of which the key is requested
134             \returns key of the packet
135             \throws PacketTypeNotRegistered if the packet type is not found in the registry.
136          */
137         template <class PacketType>
138         static typename Tag::key_t key();
139
140         /** \brief Find key of a packet type
141
142             Return the key of \a PacketType as registered in the \a Tag registry
143
144             \tparam PacketType packet of which the key is requested
145             \returns key of the packet wrapped in a <a
146                 href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
147                 an unbound optional, if the key is not found.
148          */
149         template <class PacketType>
150         static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
151
152         /** \brief Find key of a packet
153
154             Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
155
156             \param packet The packet of which the key is requested
157             \returns key of the packet
158             \throws PacketTypeNotRegistered if the packet type is not found in the registry.
159          */
160         static typename Tag::key_t key(Packet const & packet);
161
162         /** \brief Find key of a packet
163
164             Return the key of \a packet, an arbitrary packet, as registered in the \a Tag registry.
165
166             \param packet The packet of which the key is requested
167             \returns key of the packet wrapped in a <a
168                 href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
169                 an unbound optional, if the key is not found.
170          */
171         static typename boost::optional<typename Tag::key_t> key(Packet const & packet, NoThrow_t);
172
173         /** \brief Lookup a packet by it's key
174
175             \throws PacketTypeNotRegistered if the \a key is not found in the registry
176             \return %Packet entry for given \a key
177          */
178         static PkReg_Entry const & lookup(typename Tag::key_t key);
179
180         /** \brief Lookup a packet by it's key
181             \return Pointer to packet entry for given \a key or 0, if the key is not found in the
182                 registry.
183          */
184         static PkReg_Entry const * lookup(typename Tag::key_t key, NoThrow_t);
185
186         /** \brief Beginning iterator to list of registered keys
187          */
188         static iterator begin();
189
190         /** \brief End iterator to list of registered keys
191          */
192         static iterator end();
193
194     private:
195         typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
196         static Registry & registry();
197     };
198
199     /** \brief Statically add an entry to a packet registry
200
201         This macro will declare an anonymous global variable in such a way, that constructing this
202         variable will add a registration to the given packet registry.
203
204         \ingroup packet_module
205         \hideinitializer
206      */
207 #   define SENF_PACKET_REGISTRY_REGISTER( registry, value, type )                                 \
208         namespace {                                                                               \
209             senf::PacketRegistry< registry >::RegistrationProxy< type >                           \
210                 BOOST_PP_CAT(packetRegistration_, __LINE__) ( value );                            \
211         }
212
213     /** \brief Dump all packet registries
214
215         This command will dump all packet registries to the given stream. This is to help debugging
216         registration problems.
217      */
218     void dumpPacketRegistries(std::ostream & os);
219
220     /** \brief Entry not found in registry
221
222         This exception is signaled whenever a throwing lookup operation fails.
223      */
224     struct PacketTypeNotRegisteredException : public senf::Exception
225     { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered") {} };
226
227 }
228
229 ///////////////////////////////hh.e////////////////////////////////////////
230 #endif
231 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
232 #define HH_SENF_Packets_PacketRegistry_i_
233 #include "PacketRegistry.cci"
234 #include "PacketRegistry.ct"
235 #include "PacketRegistry.cti"
236 #endif
237
238 \f
239 // Local Variables:
240 // mode: c++
241 // fill-column: 100
242 // c-file-style: "senf"
243 // indent-tabs-mode: nil
244 // ispell-local-dictionary: "american"
245 // compile-command: "scons -u test"
246 // comment-column: 40
247 // End:
248