e98a8c6f1eb265b4f05a604e03bec4a5e0497353
[senf.git] / senf / Packets / PacketImpl.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
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 PacketImpl public header */
25
26 #ifndef HH_SENF_Packets_PacketImpl_
27 #define HH_SENF_Packets_PacketImpl_ 1
28
29 // Custom includes
30 #include <memory>
31 #include <vector>
32 #include <boost/utility.hpp>
33 #include <boost/type_traits/is_base_of.hpp>
34 #include <boost/type_traits/has_trivial_constructor.hpp>
35 #include <boost/type_traits/has_trivial_destructor.hpp>
36 #include <boost/static_assert.hpp>
37 #include <senf/Utils/pool_alloc_mixin.hh>
38 #include <senf/Utils/singleton.hh>
39
40 //#include "PacketImpl.mpp"
41 ///////////////////////////////hh.p////////////////////////////////////////
42
43 namespace senf {
44
45     /** \brief Marker base-class for complex annotations
46
47         This class is used as a base class to mark an annotation type as complex. A complex
48         annotation will have it's constructor/destructor called. Non-complex annotations will not
49         have their constructor called, they will be zero initialized. The destructor of non-complex
50         annotations is never called.
51
52         An annotation must be marked as complex if it is not <a
53         href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">POD</a>. Simplified, an
54         annotation must be marked as ComplexAnnotation, if
55
56         \li it has a (user defined) constructor or destructor
57         \li it has any data members which have (user defined) constructors or destructors
58
59         \see \ref packet_usage_annotation
60      */
61     struct ComplexAnnotation {};
62
63 namespace detail {
64
65     struct AnnotationP
66     {
67         virtual ~AnnotationP();
68     };
69
70     template <class Annotation>
71     struct TAnnotationP
72         : public AnnotationP
73     {
74         Annotation annotation;
75     };
76
77     union AnnotationEntry {
78         AnnotationP * p;
79         unsigned long long i;
80     };
81
82     struct AnnotationIndexerBase
83     {
84         virtual ~AnnotationIndexerBase();
85         virtual void v_dump(PacketImpl * p, std::ostream & os) = 0;
86
87         static unsigned maxAnnotations;
88         static std::vector<bool> & small();
89         static std::vector<AnnotationIndexerBase*> & registry();
90         static void dump(PacketImpl * p, std::ostream & os);
91     };
92
93     template <class Annotation>
94     struct AnnotationIndexer 
95         : public senf::singleton< AnnotationIndexer<Annotation> >, 
96           public AnnotationIndexerBase
97     {
98         AnnotationIndexer();
99         virtual void v_dump(PacketImpl * p, std::ostream & os);
100         unsigned index_;
101         static unsigned index();
102         static bool const Complex = boost::is_base_of<ComplexAnnotation, Annotation>::value;
103         static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) && ! Complex);
104
105 #       if 0 // The test is difficult since it does not work with user-defined trivial constructors
106 #       ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
107
108         BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value 
109                                && boost::has_trivial_destructor<Annotation>::value)
110                               || Complex ));
111
112 #       endif
113 #       endif
114     };
115
116     template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
117     struct GetAnnotation
118     {
119         static Annotation & get(AnnotationEntry & e);
120         static void dump(AnnotationEntry & e, std::ostream & os);
121     };
122
123     template <class Annotation>
124     struct GetAnnotation<Annotation, true>
125     {
126         static Annotation & get(AnnotationEntry & e);
127         static void dump(AnnotationEntry & e, std::ostream & os);
128     };
129
130     /** \brief Internal: Packet data storage
131
132         \internal
133
134         This is the class holding the packet data and the interpreter chain. All manipulations of
135         the packet data are performed via the interface exported here. This is very important, since
136         PacketImpl will update the interpreters (that is the vector indices stored therein) whenever
137         the data is changed.
138      */
139     class PacketImpl
140         : boost::noncopyable,
141           public pool_alloc_mixin<PacketImpl>
142     {
143     public:
144         typedef senf::detail::packet::byte byte;
145         typedef senf::detail::packet::raw_container raw_container;
146         typedef senf::detail::packet::size_type size_type;
147         typedef senf::detail::packet::difference_type difference_type;
148         typedef senf::detail::packet::interpreter_list interpreter_list;
149         typedef senf::detail::packet::iterator iterator;
150         typedef senf::detail::packet::const_iterator const_iterator;
151         typedef senf::detail::packet::refcount_t refcount_t;
152
153         // structors
154
155         PacketImpl();
156         PacketImpl(size_type size, byte initValue);
157         template <class InputIterator>
158         PacketImpl(InputIterator b, InputIterator e);
159         ~PacketImpl();
160
161         // rerference/memory management
162
163         void add_ref(refcount_t n=1);
164         void release(refcount_t n=1);
165         refcount_t refcount() const;
166
167         // Interpreter chain
168
169         PacketInterpreterBase * first();
170         PacketInterpreterBase * last();
171
172         PacketInterpreterBase * next(PacketInterpreterBase * p);
173         PacketInterpreterBase * prev(PacketInterpreterBase * p);
174
175         void appendInterpreter    (PacketInterpreterBase * p);
176         void prependInterpreter   (PacketInterpreterBase * p);
177         void prependInterpreter   (PacketInterpreterBase * p, PacketInterpreterBase * before);
178         void truncateInterpreters (PacketInterpreterBase * p);
179         void truncateInterpretersBackwards (PacketInterpreterBase * p);
180
181         // Data container
182
183         iterator begin();
184         iterator end();
185         size_type size();
186
187         void insert(PacketData * self, iterator pos, byte v);
188         void insert(PacketData * self, iterator pos, size_type n, byte v);
189         template <class ForwardIterator>
190         void insert(PacketData * self, iterator pos, ForwardIterator f, ForwardIterator l);
191
192         void erase(PacketData * self, iterator pos);
193         void erase(PacketData * self, iterator first, iterator last);
194         void clear(PacketData * self);
195
196         void reserve(size_type n);
197         size_type capacity() const;
198
199         // Annotations
200         template <class Annotation>
201         Annotation & annotation();
202         void dumpAnnotations(std::ostream & os);
203         template <class Annotation>
204         void dumpAnnotation(std::ostream & os);
205
206         /** \brief Internal: Keep PacketImpl instance alive
207
208             \internal
209
210             The Guard will keep the PacketImpl instance alive during a members execution time
211             It the refcount should drop to 0, PacketImpl will be deleted after the member
212             has completed executing.
213          */
214         struct Guard {
215             Guard(PacketImpl * impl);
216             ~Guard();
217             PacketImpl * p;
218         };
219
220     private:
221         refcount_t refcount_;
222         raw_container data_;
223         interpreter_list interpreters_;
224         
225         typedef std::vector<AnnotationEntry> Annotations;
226         Annotations annotations_;
227
228         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
229         void updateIterators(PacketData * self, difference_type pos, difference_type n);
230     };
231
232 }}
233
234 ///////////////////////////////hh.e////////////////////////////////////////
235 #endif
236 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
237 #define HH_SENF_Packets_PacketImpl_i_
238 #include "PacketImpl.cci"
239 //#include "PacketImpl.ct"
240 #include "PacketImpl.cti"
241 #endif
242
243 \f
244 // Local Variables:
245 // mode: c++
246 // fill-column: 100
247 // c-file-style: "senf"
248 // indent-tabs-mode: nil
249 // ispell-local-dictionary: "american"
250 // compile-command: "scons -u test"
251 // comment-column: 40
252 // End:
253