git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@129 270642c3-0616-0410...
[senf.git] / Packets / PacketRegistry.hh
1 // $Id$
2 //
3 // Copyright (C) 2006 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 // TODO: Add parameterless create() method
24
25 #ifndef HH_PacketRegistryImpl_
26 #define HH_PacketRegistryImpl_ 1
27
28 // Custom includes
29 #include <map>
30 #include <boost/utility.hpp> // for boost::noncopyable
31 #include <boost/shared_ptr.hpp>
32 #include "Packet.hh"
33
34 //#include "PacketRegistry.mpp"
35 ///////////////////////////////hh.p////////////////////////////////////////
36
37 namespace satcom {
38 namespace pkf {
39
40     namespace impl { template <class key> class PacketRegistryImpl; }
41
42     /** \brief Packet registration facility
43
44         The PacketRegistry provides a generic facility to associate an
45         arbitrary key with Packets. Example keys are Ethertype or IP
46         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 valuetype. The PacketRegistry
55         for this Tag can then be accessed using
56         <code>PacketRegistry<SomeTag>::</code>.
57
58         The PacketRegistry class has only static members and provides
59         access to the packet registry. It allows to register Packet
60         classes and to create new Packets given a key. Methods are
61         also provided to find the key of a Packet type.
62
63         \code
64             PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
65             p = PacketRegistry<SomeTag>::create(some_key,begin,end);
66             SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
67         \endcode
68
69         Normally, packet classes are registered statically and not
70         procedurally. To this end, the RegistrationProxy is provided:
71         \code
72           PacketRegistry<SomeTag>::RegistrationProxy<SomePacket> 
73               registerSomePacket (key_of_somePacket);
74         \endcode
75         This global variable declaration will register \c SomePacket
76         with the \c SomeTag registry under the key \c
77         key_of_somePacket. The variable \c registerSomePacket is a
78         dummy. It's only function is to force the call of it's
79         constructor during global construction time.
80
81         The PacketRegistry's purpose is mostly to assist in
82         implementing the \v v_nextInterpreter() member of packet
83         facades. This is further supported by the PacketRegistryMixin
84         class.
85      */
86     template <class Tag>
87     class PacketRegistry
88     {
89     public:
90         // TODO: This fails to work within a library since the linker will
91         // remove all unused object files ...
92         /** \brief Statically register a packet type in a PacketRegistry
93          */
94         template <class OtherPacket>
95         struct RegistrationProxy
96         {
97             RegistrationProxy(typename Tag::key_t key);
98         };
99         
100         /** \brief Register new packet type
101             
102             Register \c OtherPacket in the packet registry \c Tag
103             under the given \c key.
104
105             \par Preconditions:
106                 The given \c key must be unique and not be assigned to
107                 any other packet class in this registry.
108                 The Packet must not already be registered in the registry.
109
110             \param OtherPacket packet to regiser
111             \param key key of the packet
112          */
113         template <class OtherPacket>
114         static void registerPacket(typename Tag::key_t key);
115
116         /** \brief Find key of a packet
117             
118             Return the key of \c OtherPacket as registered in the \c
119             Tag registry
120
121             \param OtherPacket packet of which the key is requested
122             \returns key of the packet
123             \throws PacketTypeNotRegistered if the packet type is not
124                 found in the registry.
125          */
126         template <class OtherPacket>
127         static typename Tag::key_t key();
128
129         /** \brief Create new Packet
130
131             \param key Key of packet type to create instance of
132             \param b begin iterator argument to Packet::create()
133             \param e end iterator argment to Packet::create()
134             \returns new Instance of the packet type registered under
135                 key or DataPacket, if the key is not registered.
136          */
137         template <class InputIterator>
138         static Packet::ptr create(typename Tag::key_t key, InputIterator b, InputIterator e);
139         
140     private:
141         typedef impl::PacketRegistryImpl<typename Tag::key_t> Registry;
142         static Registry & registry();
143         
144         template <class T, class D> friend class PacketRegistryMixin;
145     };
146
147     /** \brief Helper class for v_nextInterpreter implementations
148
149         This class is a helper class which is to be inherited from in
150         a packet facade which wants to register a new interpreter with
151         the packet framework depending on a packet registry.
152
153         This mixin class provides a new registerInterpreter
154         implementation which can be used besides the methods provided
155         bei satcom::pkf::Packet to add a new interpreter to the
156         interpreter chain.
157
158         \code
159           class SomePacket
160               : public Packet,
161                 private PacketRegistryMixin<SomeTag,SomePacket>
162           {
163               using Packet::retgisterInterpreter;
164               using PacketRegistryMixin<SomeTag,SomePacket>::registerInterpreter;
165
166               virtual void v_nextInterpreter()
167               {
168                   registerInterpreter(some_key_value, subpacket_begin, subpacket_end);
169               }
170           };
171         \endcode
172         This example is not complete, it only contains the parts
173         concerned with PacketRegistryMixin.
174      */
175     template <class Tag, class Derived>
176     class PacketRegistryMixin
177     {
178     protected:
179         /** \brief add interpreter to interpreter chain
180             
181             This method is used by v_nextInterpreter() to add a new
182             interpreter to the interpreter chain (see the Packet
183             reference for more). Instead of specifying the type of
184             packet to use as a template argument it is specified using
185             the \c key value from the \c Tag registry
186          */
187         void registerInterpreter(typename Tag::key_t key, 
188                                  Packet::iterator b, Packet::iterator e) const;
189     };
190
191     struct PacketTypeNotRegistered : public std::exception
192     { virtual char const * what() const throw() { return "packet type not registered"; } };
193
194 }}
195
196 ///////////////////////////////hh.e////////////////////////////////////////
197 //#include "PacketRegistry.cci"
198 #include "PacketRegistry.ct"
199 #include "PacketRegistry.cti"
200 #endif
201
202 \f
203 // Local Variables:
204 // mode: c++
205 // c-file-style: "satcom"
206 // End: