Packets: static assertion for duplicate tlv parser registration
[senf.git] / senf / Packets / PacketRegistry.ih
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief PacketRegistry internal header */
30
31 #ifndef IH_SENF_Packets_PacketRegistry_
32 #define IH_SENF_Packets_PacketRegistry_ 1
33
34 // Custom includes
35 #include <limits>
36 #include <boost/multi_index_container.hpp>
37 #include <boost/multi_index/ordered_index.hpp>
38 #include <boost/multi_index/composite_key.hpp>
39 #include <boost/multi_index/member.hpp>
40 #include <boost/multi_index/mem_fun.hpp>
41 #include <boost/intrusive_ptr.hpp>
42 #include <boost/utility.hpp> // for boost::noncopyable
43 #include <senf/Utils/TypeIdValue.hh>
44
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46
47 namespace senf {
48 namespace detail {
49
50     struct TypeInfoCompare
51     {
52         bool operator()(std::type_info const & a, std::type_info const & b) const
53             { return a.before(b); }
54     };
55
56     /** \brief Internal: Registry implementation base-class and registry of registries
57
58         \internal
59      */
60     class PacketRegistryImplBase
61         : private boost::noncopyable
62     {
63     public:
64         virtual ~PacketRegistryImplBase();
65
66         static void dump(std::ostream & os);
67         static void clear();
68
69     protected:
70         typedef std::map<std::string, PacketRegistryImplBase*>  RegistryMap;
71         static RegistryMap & registries();
72
73     private:
74         virtual bool v_empty() const = 0;
75         virtual void v_dump(std::ostream & os) const = 0;
76         virtual void v_clear() = 0;
77     };
78
79     /** \brief Internal: Singleton class implementing the packet registry.
80
81         \internal
82      */
83     template <class KeyType>
84     class PacketRegistryImpl
85         : public PacketRegistryImplBase
86     {
87     public:
88         typedef KeyType key_t;
89
90         struct Entry : public intrusive_refcount
91         {
92             typedef boost::intrusive_ptr<Entry> ptr;
93
94             Entry(KeyType const & key_, int priority_);
95             virtual ~Entry();
96
97             virtual Packet::factory_t factory() const = 0;
98
99             virtual std::string name() const = 0;
100             virtual std::type_info const & type() const = 0;
101
102             KeyType key;
103             int priority;
104         };
105
106     private:
107         struct ByKey {};
108         struct ByType {};
109
110         struct RegistryIndices
111             : public boost::multi_index::indexed_by<
112                 boost::multi_index::ordered_unique<
113                     boost::multi_index::tag<ByKey>,
114                     boost::multi_index::composite_key<
115                         Entry,
116                         boost::multi_index::member<Entry,KeyType,&Entry::key>,
117                         boost::multi_index::member<Entry,int,&Entry::priority> >,
118                     boost::multi_index::composite_key_compare<
119                         std::less<KeyType>,
120                         std::greater<int> > >,
121                 boost::multi_index::ordered_unique<
122                     boost::multi_index::tag<ByType>,
123                     boost::multi_index::mem_fun<Entry const,std::type_info const &,&Entry::type>,
124                     TypeInfoCompare> >
125         {};
126
127         typedef boost::multi_index_container<typename Entry::ptr, RegistryIndices> Registry;
128         typedef typename Registry::template index<ByKey>::type RegistryByKey;
129         typedef typename Registry::template index<ByType>::type RegistryByType;
130
131         template <class PacketType>
132         struct EntryImpl : public Entry
133         {
134             EntryImpl(KeyType const & key, int priority);
135
136             virtual Packet::factory_t factory() const;
137             virtual std::string name() const;
138             virtual std::type_info const & type() const;
139         };
140
141     public:
142         //-/////////////////////////////////////////////////////////////////////////////////////////
143         // Types
144
145         typedef typename Registry::template index<ByKey>::type::const_iterator iterator;
146
147         //-/////////////////////////////////////////////////////////////////////////////////////////
148         ///\name Structors and default members
149         //\{
150
151         PacketRegistryImpl(std::string const & name);
152
153         //\}
154         //-/////////////////////////////////////////////////////////////////////////////////////////
155
156         template <class PacketType>
157         void registerPacket(key_t key, int priority=0);
158
159         template <class PacketType>
160         void unregisterPacket();
161         void unregisterPacket(key_t key, int priority=0);
162
163         key_t key(senf::TypeIdValue const & type);
164         boost::optional<key_t> key(senf::TypeIdValue const & type, bool);
165
166         Entry const & lookup(key_t key) const;
167         Entry const * lookup(key_t key, bool) const;
168
169         iterator begin() const;
170         iterator end() const;
171
172     protected:
173
174     private:
175         virtual bool v_empty() const;
176         virtual void v_dump(std::ostream & os) const;
177         virtual void v_clear();
178
179         Registry registry_;
180         RegistryByKey & registryByKey_;
181         RegistryByType & registryByType_;
182     };
183
184     template <class KeyType, bool is_integral=std::numeric_limits<KeyType>::is_integer>
185     struct DumpKey
186     {
187         static void dump(KeyType const & v, std::ostream & os);
188     };
189
190     template <class KeyType>
191     struct DumpKey<KeyType, true>
192     {
193         static void dump(KeyType const & v, std::ostream & os);
194     };
195
196 }}
197
198 //-/////////////////////////////////////////////////////////////////////////////////////////////////
199 #endif
200
201 \f
202 // Local Variables:
203 // mode: c++
204 // fill-column: 100
205 // c-file-style: "senf"
206 // indent-tabs-mode: nil
207 // ispell-local-dictionary: "american"
208 // compile-command: "scons -u test"
209 // comment-column: 40
210 // End: