switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Packets / PacketImpl.ih
1 // $Id$
2 //
3 // Copyright (C) 2010
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 PacketImpl internal header */
30
31 #ifndef IH_SENF_senf_Packets_PacketImpl_
32 #define IH_SENF_senf_Packets_PacketImpl_ 1
33
34 // Custom includes
35 #include <iostream>
36 #include <map>
37 #include <string>
38 #include <ext/functional>
39 #include <boost/iterator/transform_iterator.hpp>
40 #include <boost/type_traits/is_convertible.hpp>
41 #include <boost/mpl/sizeof.hpp>
42 #include <boost/mpl/int.hpp>
43 #include <boost/mpl/or.hpp>
44 #include <boost/mpl/greater.hpp>
45 #include <boost/ptr_container/ptr_map.hpp>
46 #include <senf/Utils/TypeInfo.hh>
47 #include <senf/Utils/singleton.hh>
48 #include <senf/config.hh>
49 #include <senf/Utils/IgnoreValue.hh>
50
51 //-/////////////////////////////////////////////////////////////////////////////////////////////////
52
53 namespace senf {
54
55     struct ComplexAnnotation;
56
57 namespace detail {
58
59     template <class Annotation>
60     struct IsComplexAnnotation
61         : public boost::mpl::or_< boost::is_convertible<Annotation*, ComplexAnnotation*>,
62                                   boost::mpl::greater<
63                                       boost::mpl::sizeof_<Annotation>,
64                                       boost::mpl::int_<SENF_PACKET_ANNOTATION_SLOTSIZE> > >
65     {};
66
67     class AnnotationRegistry
68         : public senf::singleton<AnnotationRegistry>
69     {
70     public:
71         typedef int key_type;
72
73     private:
74         struct RegistrationBase
75         {
76             virtual ~RegistrationBase () {};
77             key_type key;
78             virtual void v_dump(std::ostream & os, void * annotation) const = 0;
79             virtual std::string v_name() const = 0;
80             virtual bool v_isComplex() const = 0;
81             virtual unsigned v_size() const = 0;
82         };
83
84         template <class Annotation>
85         struct Registration
86             : public RegistrationBase
87         {
88             void v_dump(std::ostream & os, void * annotation) const
89                 { os << * static_cast<Annotation*>(annotation); }
90             std::string v_name() const
91                 { return prettyName(typeid(Annotation)); }
92             bool v_isComplex() const
93                 { return boost::is_convertible<Annotation*, ComplexAnnotation*>::value; }
94             unsigned v_size() const
95                 { return sizeof(Annotation); }
96         };
97
98         typedef boost::ptr_map<key_type, RegistrationBase> Registry;
99         // Index must be a multi-map since two identically named classes
100         // both in the anonymous namespace both have the same demangled name.
101         // we could sort on the mangled name instead ...
102         typedef std::multimap<std::string, key_type> Index;
103
104     public:
105         typedef boost::transform_iterator< ::__gnu_cxx::select2nd<Index::value_type>,
106                                            Index::const_iterator > iterator;
107
108         using senf::singleton<AnnotationRegistry>::instance;
109
110         template <class Annotation> class RegistrationProxy;
111
112         class EntryBase;
113         template <class Annotation> class Entry;
114
115         template <class Annotation>
116         key_type registerAnnotation();
117
118         void dump(key_type key, std::ostream & os, void * annotation) const;
119         std::string name(key_type key) const;
120         bool isComplex(key_type key) const;
121         unsigned size(key_type key) const;
122
123         template <class Annotation>
124         static key_type lookup();
125
126         iterator begin() const;
127         iterator end() const;
128
129         void dumpRegistrations(std::ostream & os);
130
131     private:
132         AnnotationRegistry();
133
134         key_type simpleAnnotationCount_;
135         key_type complexAnnotationCount_;
136
137         Registry registry_;
138         // The index is needed to ensure a persistent and reproducible
139         // ordering of the annotations when dumping
140         Index index_;
141
142         friend class senf::singleton<AnnotationRegistry>;
143     };
144
145     template <class Annotation>
146     class AnnotationRegistry::RegistrationProxy
147     {
148     public:
149         RegistrationProxy()
150             {
151                 AnnotationRegistry::Entry<Annotation>::key_ =
152                     AnnotationRegistry::instance().registerAnnotation<Annotation>();
153             }
154     };
155
156     class AnnotationRegistry::EntryBase
157     {
158     public:
159         virtual ~EntryBase() {}
160
161         virtual void * get() = 0;
162
163         typedef EntryBase * ptr;
164         virtual ptr clone() const = 0;
165     };
166
167     inline AnnotationRegistry::EntryBase::ptr new_clone( AnnotationRegistry::EntryBase const & entry)
168     {
169         return entry.clone();
170     }
171
172     template <class Annotation>
173     class AnnotationRegistry::Entry
174         : public AnnotationRegistry::EntryBase
175     {
176         static RegistrationProxy<Annotation> proxy_;
177         static AnnotationRegistry::key_type key_;
178     public:
179         // We use this member to force instantiation of proxy_ ...
180         static AnnotationRegistry::key_type key()
181             { senf::IGNORE(&proxy_); return key_; }
182
183         virtual void * get() { return & annotation_; }
184         virtual EntryBase::ptr clone() const { return new Entry<Annotation>( *this); }
185
186     private:
187         Annotation annotation_;
188
189         friend class AnnotationRegistry::RegistrationProxy<Annotation>;
190     };
191
192 }}
193
194 //-/////////////////////////////////////////////////////////////////////////////////////////////////
195 #endif
196
197 \f
198 // Local Variables:
199 // mode: c++
200 // fill-column: 100
201 // comment-column: 40
202 // c-file-style: "senf"
203 // indent-tabs-mode: nil
204 // ispell-local-dictionary: "american"
205 // compile-command: "scons -u test"
206 // End: